summaryrefslogtreecommitdiff
path: root/vendor/exr/src/image/read/levels.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
committerValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
commit1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch)
tree7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/exr/src/image/read/levels.rs
parent5ecd8cf2cba827454317368b68571df0d13d7842 (diff)
downloadfparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz
fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/exr/src/image/read/levels.rs')
-rw-r--r--vendor/exr/src/image/read/levels.rs219
1 files changed, 219 insertions, 0 deletions
diff --git a/vendor/exr/src/image/read/levels.rs b/vendor/exr/src/image/read/levels.rs
new file mode 100644
index 0000000..5705903
--- /dev/null
+++ b/vendor/exr/src/image/read/levels.rs
@@ -0,0 +1,219 @@
+//! How to read a set of resolution levels.
+
+use crate::meta::*;
+use crate::image::*;
+use crate::error::*;
+use crate::meta::attribute::*;
+use crate::image::read::any_channels::*;
+use crate::block::chunk::TileCoordinates;
+use crate::image::read::specific_channels::*;
+use crate::image::recursive::*;
+use crate::math::Vec2;
+use crate::block::lines::LineRef;
+use crate::block::samples::*;
+use crate::meta::header::{Header};
+
+
+// Note: In the resulting image, the `FlatSamples` are placed
+// directly inside the channels, without `LargestLevel<>` indirection
+/// Specify to read only the highest resolution level, skipping all smaller variations.
+/// The sample storage can be [`ReadFlatSamples`].
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct ReadLargestLevel<DeepOrFlatSamples> {
+
+ /// The sample reading specification
+ pub read_samples: DeepOrFlatSamples
+}
+
+
+// FIXME rgba levels???
+
+// Read the largest level, directly, without intermediate structs
+impl<DeepOrFlatSamples> ReadLargestLevel<DeepOrFlatSamples> {
+
+ /// Read all arbitrary channels in each layer.
+ pub fn all_channels(self) -> ReadAnyChannels<DeepOrFlatSamples> { ReadAnyChannels { read_samples: self.read_samples } } // Instead of Self, the `FlatSamples` are used directly
+
+ /// Read only layers that contain rgba channels. Skips any other channels in the layer.
+ /// The alpha channel will contain the value `1.0` if no alpha channel can be found in the image.
+ ///
+ /// Using two closures, define how to store the pixels.
+ /// The first closure creates an image, and the second closure inserts a single pixel.
+ /// The type of the pixel can be defined by the second closure;
+ /// it must be a tuple containing four values, each being either `f16`, `f32`, `u32` or `Sample`.
+ ///
+ /// Throws an error for images with deep data or subsampling.
+ /// Use `specific_channels` or `all_channels` if you want to read something other than rgba.
+ pub fn rgba_channels<R,G,B,A, Create, Set, Pixels>(
+ self, create_pixels: Create, set_pixel: Set
+ ) -> CollectPixels<
+ ReadOptionalChannel<ReadRequiredChannel<ReadRequiredChannel<ReadRequiredChannel<NoneMore, R>, G>, B>, A>,
+ (R, G, B, A), Pixels, Create, Set
+ >
+ where
+ R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample,
+ Create: Fn(Vec2<usize>, &RgbaChannels) -> Pixels,
+ Set: Fn(&mut Pixels, Vec2<usize>, (R,G,B,A)),
+ {
+ self.specific_channels()
+ .required("R").required("G").required("B")
+ .optional("A", A::from_f32(1.0))
+ .collect_pixels(create_pixels, set_pixel)
+ }
+
+ /// Read only layers that contain rgb channels. Skips any other channels in the layer.
+ ///
+ /// Using two closures, define how to store the pixels.
+ /// The first closure creates an image, and the second closure inserts a single pixel.
+ /// The type of the pixel can be defined by the second closure;
+ /// it must be a tuple containing three values, each being either `f16`, `f32`, `u32` or `Sample`.
+ ///
+ /// Throws an error for images with deep data or subsampling.
+ /// Use `specific_channels` or `all_channels` if you want to read something other than rgb.
+ pub fn rgb_channels<R,G,B, Create, Set, Pixels>(
+ self, create_pixels: Create, set_pixel: Set
+ ) -> CollectPixels<
+ ReadRequiredChannel<ReadRequiredChannel<ReadRequiredChannel<NoneMore, R>, G>, B>,
+ (R, G, B), Pixels, Create, Set
+ >
+ where
+ R: FromNativeSample, G: FromNativeSample, B: FromNativeSample,
+ Create: Fn(Vec2<usize>, &RgbChannels) -> Pixels,
+ Set: Fn(&mut Pixels, Vec2<usize>, (R,G,B)),
+ {
+ self.specific_channels()
+ .required("R").required("G").required("B")
+ .collect_pixels(create_pixels, set_pixel)
+ }
+
+ /// Read only layers that contain the specified channels, skipping any other channels in the layer.
+ /// Further specify which channels should be included by calling `.required("ChannelName")`
+ /// or `.optional("ChannelName", default_value)` on the result of this function.
+ /// Call `collect_pixels` afterwards to define the pixel container for your set of channels.
+ ///
+ /// Throws an error for images with deep data or subsampling.
+ pub fn specific_channels(self) -> ReadZeroChannels {
+ ReadZeroChannels { }
+ }
+}
+
+/// Specify to read all contained resolution levels from the image, if any.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct ReadAllLevels<DeepOrFlatSamples> {
+
+ /// The sample reading specification
+ pub read_samples: DeepOrFlatSamples
+}
+
+impl<ReadDeepOrFlatSamples> ReadAllLevels<ReadDeepOrFlatSamples> {
+
+ /// Read all arbitrary channels in each layer.
+ pub fn all_channels(self) -> ReadAnyChannels<Self> { ReadAnyChannels { read_samples: self } }
+
+ // TODO specific channels for multiple resolution levels
+
+}
+
+/*pub struct ReadLevels<S> {
+ read_samples: S,
+}*/
+
+/// Processes pixel blocks from a file and accumulates them into multiple levels per channel.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct AllLevelsReader<SamplesReader> {
+ levels: Levels<SamplesReader>,
+}
+
+/// A template that creates a [`SamplesReader`] once for each resolution level.
+pub trait ReadSamplesLevel {
+
+ /// The type of the temporary level reader
+ type Reader: SamplesReader;
+
+ /// Create a single reader for a single resolution level
+ fn create_samples_level_reader(&self, header: &Header, channel: &ChannelDescription, level: Vec2<usize>, resolution: Vec2<usize>) -> Result<Self::Reader>;
+}
+
+
+impl<S: ReadSamplesLevel> ReadSamples for ReadAllLevels<S> {
+ type Reader = AllLevelsReader<S::Reader>;
+
+ fn create_sample_reader(&self, header: &Header, channel: &ChannelDescription) -> Result<Self::Reader> {
+ let data_size = header.layer_size / channel.sampling;
+
+ let levels = {
+ if let crate::meta::BlockDescription::Tiles(tiles) = &header.blocks {
+ match tiles.level_mode {
+ LevelMode::Singular => Levels::Singular(self.read_samples.create_samples_level_reader(header, channel, Vec2(0,0), header.layer_size)?),
+
+ LevelMode::MipMap => Levels::Mip {
+ rounding_mode: tiles.rounding_mode,
+ level_data: {
+ let round = tiles.rounding_mode;
+ let maps: Result<LevelMaps<S::Reader>> = mip_map_levels(round, data_size)
+ .map(|(index, level_size)| self.read_samples.create_samples_level_reader(header, channel, Vec2(index, index), level_size))
+ .collect();
+
+ maps?
+ },
+ },
+
+ // TODO put this into Levels::new(..) ?
+ LevelMode::RipMap => Levels::Rip {
+ rounding_mode: tiles.rounding_mode,
+ level_data: {
+ let round = tiles.rounding_mode;
+ let level_count_x = compute_level_count(round, data_size.width());
+ let level_count_y = compute_level_count(round, data_size.height());
+ let maps: Result<LevelMaps<S::Reader>> = rip_map_levels(round, data_size)
+ .map(|(index, level_size)| self.read_samples.create_samples_level_reader(header, channel, index, level_size))
+ .collect();
+
+ RipMaps {
+ map_data: maps?,
+ level_count: Vec2(level_count_x, level_count_y)
+ }
+ },
+ },
+ }
+ }
+
+ // scan line blocks never have mip maps
+ else {
+ Levels::Singular(self.read_samples.create_samples_level_reader(header, channel, Vec2(0, 0), data_size)?)
+ }
+ };
+
+ Ok(AllLevelsReader { levels })
+ }
+}
+
+
+impl<S: SamplesReader> SamplesReader for AllLevelsReader<S> {
+ type Samples = Levels<S::Samples>;
+
+ fn filter_block(&self, _: TileCoordinates) -> bool {
+ true
+ }
+
+ fn read_line(&mut self, line: LineRef<'_>) -> UnitResult {
+ self.levels.get_level_mut(line.location.level)?.read_line(line)
+ }
+
+ fn into_samples(self) -> Self::Samples {
+ match self.levels {
+ Levels::Singular(level) => Levels::Singular(level.into_samples()),
+ Levels::Mip { rounding_mode, level_data } => Levels::Mip {
+ rounding_mode, level_data: level_data.into_iter().map(|s| s.into_samples()).collect(),
+ },
+
+ Levels::Rip { rounding_mode, level_data } => Levels::Rip {
+ rounding_mode,
+ level_data: RipMaps {
+ level_count: level_data.level_count,
+ map_data: level_data.map_data.into_iter().map(|s| s.into_samples()).collect(),
+ }
+ },
+ }
+ }
+}