//! 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 { /// The sample reading specification pub read_samples: DeepOrFlatSamples } // FIXME rgba levels??? // Read the largest level, directly, without intermediate structs impl ReadLargestLevel { /// Read all arbitrary channels in each layer. pub fn all_channels(self) -> ReadAnyChannels { 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( self, create_pixels: Create, set_pixel: Set ) -> CollectPixels< ReadOptionalChannel, G>, B>, A>, (R, G, B, A), Pixels, Create, Set > where R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample, Create: Fn(Vec2, &RgbaChannels) -> Pixels, Set: Fn(&mut Pixels, Vec2, (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( self, create_pixels: Create, set_pixel: Set ) -> CollectPixels< ReadRequiredChannel, G>, B>, (R, G, B), Pixels, Create, Set > where R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, Create: Fn(Vec2, &RgbChannels) -> Pixels, Set: Fn(&mut Pixels, Vec2, (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 { /// The sample reading specification pub read_samples: DeepOrFlatSamples } impl ReadAllLevels { /// Read all arbitrary channels in each layer. pub fn all_channels(self) -> ReadAnyChannels { ReadAnyChannels { read_samples: self } } // TODO specific channels for multiple resolution levels } /*pub struct ReadLevels { 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 { levels: Levels, } /// 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, resolution: Vec2) -> Result; } impl ReadSamples for ReadAllLevels { type Reader = AllLevelsReader; fn create_sample_reader(&self, header: &Header, channel: &ChannelDescription) -> Result { 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> = 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> = 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 SamplesReader for AllLevelsReader { type Samples = Levels; 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(), } }, } } }