diff options
author | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
commit | a990de90fe41456a23e58bd087d2f107d321f3a1 (patch) | |
tree | 15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/exr/src/image/read | |
parent | 3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff) | |
download | fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip |
Deleted vendor folder
Diffstat (limited to 'vendor/exr/src/image/read')
-rw-r--r-- | vendor/exr/src/image/read/any_channels.rs | 128 | ||||
-rw-r--r-- | vendor/exr/src/image/read/image.rs | 209 | ||||
-rw-r--r-- | vendor/exr/src/image/read/layers.rs | 204 | ||||
-rw-r--r-- | vendor/exr/src/image/read/levels.rs | 219 | ||||
-rw-r--r-- | vendor/exr/src/image/read/mod.rs | 207 | ||||
-rw-r--r-- | vendor/exr/src/image/read/samples.rs | 122 | ||||
-rw-r--r-- | vendor/exr/src/image/read/specific_channels.rs | 463 |
7 files changed, 0 insertions, 1552 deletions
diff --git a/vendor/exr/src/image/read/any_channels.rs b/vendor/exr/src/image/read/any_channels.rs deleted file mode 100644 index 054a7c3..0000000 --- a/vendor/exr/src/image/read/any_channels.rs +++ /dev/null @@ -1,128 +0,0 @@ -//! How to read arbitrary channels. - -use crate::image::*; -use crate::meta::header::{Header}; -use crate::error::{Result, UnitResult}; -use crate::block::UncompressedBlock; -use crate::block::lines::{LineRef}; -use crate::math::Vec2; -use crate::meta::attribute::{Text, ChannelDescription}; -use crate::image::read::layers::{ReadChannels, ChannelsReader}; -use crate::block::chunk::TileCoordinates; - -/// A template that creates an [AnyChannelsReader] for each layer in the image. -/// This loads all channels for each layer. -/// The `ReadSamples` can, for example, be [ReadFlatSamples] or [ReadAllLevels<ReadFlatSamples>]. -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct ReadAnyChannels<ReadSamples> { - - /// The sample reading specification - pub read_samples: ReadSamples -} - -/// A template that creates a new [`SampleReader`] for each channel in each layer. -pub trait ReadSamples { - - /// The type of the temporary samples reader - type Reader: SamplesReader; - - /// Create a single reader for a single channel of a layer - fn create_sample_reader(&self, header: &Header, channel: &ChannelDescription) -> Result<Self::Reader>; -} - -/// Processes pixel blocks from a file and accumulates them into a collection of arbitrary channels. -/// Loads all channels for each layer. -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct AnyChannelsReader<SamplesReader> { - - /// Stores a separate sample reader per channel in the layer - sample_channels_reader: SmallVec<[AnyChannelReader<SamplesReader>; 4]>, -} - -/// Processes pixel blocks from a file and accumulates them into a single arbitrary channel. -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct AnyChannelReader<SamplesReader> { - - /// The custom reader that accumulates the pixel data for a single channel - samples: SamplesReader, - - /// Temporarily accumulated meta data. - name: Text, - - /// Temporarily accumulated meta data. - sampling_rate: Vec2<usize>, - - /// Temporarily accumulated meta data. - quantize_linearly: bool, -} - -/// Processes pixel blocks from a file and accumulates them into a single pixel channel. -/// For example, stores thousands of "Red" pixel values for a single layer. -pub trait SamplesReader { - - /// The type of resulting sample storage - type Samples; - - /// Specify whether a single block of pixels should be loaded from the file - fn filter_block(&self, tile: TileCoordinates) -> bool; - - /// Load a single pixel line, which has not been filtered, into the reader, accumulating the sample data - fn read_line(&mut self, line: LineRef<'_>) -> UnitResult; - - /// Deliver the final accumulated sample storage for the image - fn into_samples(self) -> Self::Samples; -} - - -impl<'s, S: 's + ReadSamples> ReadChannels<'s> for ReadAnyChannels<S> { - type Reader = AnyChannelsReader<S::Reader>; - - fn create_channels_reader(&self, header: &Header) -> Result<Self::Reader> { - let samples: Result<_> = header.channels.list.iter() - .map(|channel: &ChannelDescription| Ok(AnyChannelReader { - samples: self.read_samples.create_sample_reader(header, channel)?, - name: channel.name.clone(), - sampling_rate: channel.sampling, - quantize_linearly: channel.quantize_linearly - })) - .collect(); - - Ok(AnyChannelsReader { sample_channels_reader: samples? }) - } -} - -impl<S: SamplesReader> ChannelsReader for AnyChannelsReader<S> { - type Channels = AnyChannels<S::Samples>; - - fn filter_block(&self, tile: TileCoordinates) -> bool { - self.sample_channels_reader.iter().any(|channel| channel.samples.filter_block(tile)) - } - - fn read_block(&mut self, header: &Header, decompressed: UncompressedBlock) -> UnitResult { - /*for (bytes, line) in LineIndex::lines_in_block(decompressed.index, header) { - let channel = self.sample_channels_reader.get_mut(line.channel).unwrap(); - channel.samples.read_line(LineSlice { location: line, value: &decompressed.data[bytes] })?; - } - - Ok(())*/ - for line in decompressed.lines(&header.channels) { - self.sample_channels_reader[line.location.channel].samples.read_line(line)?; - } - - Ok(()) - } - - fn into_channels(self) -> Self::Channels { - AnyChannels { // not using `new()` as the channels are already sorted - list: self.sample_channels_reader.into_iter() - .map(|channel| AnyChannel { - sample_data: channel.samples.into_samples(), - - name: channel.name, - quantize_linearly: channel.quantize_linearly, - sampling: channel.sampling_rate - }) - .collect() - } - } -} diff --git a/vendor/exr/src/image/read/image.rs b/vendor/exr/src/image/read/image.rs deleted file mode 100644 index fce2f52..0000000 --- a/vendor/exr/src/image/read/image.rs +++ /dev/null @@ -1,209 +0,0 @@ -//! The last wrapper of image readers, finally containing the [`from_file(path)`] method. -//! This completes the builder and reads a complete image. - -use crate::image::*; -use crate::meta::header::{Header, ImageAttributes}; -use crate::error::{Result, UnitResult}; -use crate::block::{UncompressedBlock, BlockIndex}; -use crate::block::chunk::TileCoordinates; -use std::path::Path; -use std::io::{Read, BufReader}; -use std::io::Seek; -use crate::meta::MetaData; -use crate::block::reader::ChunksReader; - -/// Specify whether to read the image in parallel, -/// whether to use pedantic error handling, -/// and a callback for the reading progress. -#[derive(Debug, Clone)] -pub struct ReadImage<OnProgress, ReadLayers> { - on_progress: OnProgress, - read_layers: ReadLayers, - pedantic: bool, - parallel: bool, -} - -impl<F, L> ReadImage<F, L> where F: FnMut(f64) -{ - /// Uses relaxed error handling and parallel decompression. - pub fn new(read_layers: L, on_progress: F) -> Self { - Self { - on_progress, read_layers, - pedantic: false, parallel: true, - } - } - - /// Specify that any missing or unusual information should result in an error. - /// Otherwise, `exrs` will try to compute or ignore missing information. - /// - /// If pedantic is true, then an error will be returned as soon as anything is missing in the file, - /// or two values in the image contradict each other. If pedantic is false, - /// then only fatal errors will be thrown. By default, reading an image is not pedantic, - /// which means that slightly invalid files might still be readable. - /// For example, if some attribute is missing but can be recomputed, this flag decides whether an error is thrown. - /// Or if the pedantic flag is true and there are still bytes left after the decompression algorithm finished, - /// an error is thrown, because this should not happen and something might be wrong with the file. - /// Or if your application is a target of attacks, or if you want to emulate the original C++ library, - /// you might want to switch to pedantic reading. - pub fn pedantic(self) -> Self { Self { pedantic: true, ..self } } - - /// Specify that multiple pixel blocks should never be decompressed using multiple threads at once. - /// This might be slower but uses less memory and less synchronization. - pub fn non_parallel(self) -> Self { Self { parallel: false, ..self } } - - /// Specify a function to be called regularly throughout the loading process. - /// Replaces all previously specified progress functions in this reader. - pub fn on_progress<OnProgress>(self, on_progress: OnProgress) -> ReadImage<OnProgress, L> - where OnProgress: FnMut(f64) - { - ReadImage { - on_progress, - read_layers: self.read_layers, - pedantic: self.pedantic, - parallel: self.parallel - } - } - - - /// Read the exr image from a file. - /// Use [`ReadImage::read_from_unbuffered`] instead, if you do not have a file. - #[inline] - #[must_use] - pub fn from_file<Layers>(self, path: impl AsRef<Path>) -> Result<Image<Layers>> - where for<'s> L: ReadLayers<'s, Layers = Layers> - { - self.from_unbuffered(std::fs::File::open(path)?) - } - - /// Buffer the reader and then read the exr image from it. - /// Use [`ReadImage::read_from_buffered`] instead, if your reader is an in-memory reader. - /// Use [`ReadImage::read_from_file`] instead, if you have a file path. - #[inline] - #[must_use] - pub fn from_unbuffered<Layers>(self, unbuffered: impl Read + Seek) -> Result<Image<Layers>> - where for<'s> L: ReadLayers<'s, Layers = Layers> - { - self.from_buffered(BufReader::new(unbuffered)) - } - - /// Read the exr image from a buffered reader. - /// Use [`ReadImage::read_from_file`] instead, if you have a file path. - /// Use [`ReadImage::read_from_unbuffered`] instead, if this is not an in-memory reader. - // TODO Use Parallel<> Wrapper to only require sendable byte source where parallel decompression is required - #[must_use] - pub fn from_buffered<Layers>(self, buffered: impl Read + Seek) -> Result<Image<Layers>> - where for<'s> L: ReadLayers<'s, Layers = Layers> - { - let chunks = crate::block::read(buffered, self.pedantic)?; - self.from_chunks(chunks) - } - - /// Read the exr image from an initialized chunks reader - /// that has already extracted the meta data from the file. - /// Use [`ReadImage::read_from_file`] instead, if you have a file path. - /// Use [`ReadImage::read_from_buffered`] instead, if this is an in-memory reader. - // TODO Use Parallel<> Wrapper to only require sendable byte source where parallel decompression is required - #[must_use] - pub fn from_chunks<Layers>(mut self, chunks_reader: crate::block::reader::Reader<impl Read + Seek>) -> Result<Image<Layers>> - where for<'s> L: ReadLayers<'s, Layers = Layers> - { - let Self { pedantic, parallel, ref mut on_progress, ref mut read_layers } = self; - - let layers_reader = read_layers.create_layers_reader(chunks_reader.headers())?; - let mut image_collector = ImageWithAttributesReader::new(chunks_reader.headers(), layers_reader)?; - - let block_reader = chunks_reader - .filter_chunks(pedantic, |meta, tile, block| { - image_collector.filter_block(meta, tile, block) - })? - .on_progress(on_progress); - - // TODO propagate send requirement further upwards - if parallel { - block_reader.decompress_parallel(pedantic, |meta_data, block|{ - image_collector.read_block(&meta_data.headers, block) - })?; - } - else { - block_reader.decompress_sequential(pedantic, |meta_data, block|{ - image_collector.read_block(&meta_data.headers, block) - })?; - } - - Ok(image_collector.into_image()) - } -} - -/// Processes blocks from a file and collects them into a complete `Image`. -#[derive(Debug, Clone, PartialEq)] -pub struct ImageWithAttributesReader<L> { - image_attributes: ImageAttributes, - layers_reader: L, -} - -impl<L> ImageWithAttributesReader<L> where L: LayersReader { - - /// A new image reader with image attributes. - pub fn new(headers: &[Header], layers_reader: L) -> Result<Self> - { - Ok(ImageWithAttributesReader { - image_attributes: headers.first().as_ref().expect("invalid headers").shared_attributes.clone(), - layers_reader, - }) - } - - /// Specify whether a single block of pixels should be loaded from the file - fn filter_block(&self, meta: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool { - self.layers_reader.filter_block(meta, tile, block) - } - - /// Load a single pixel block, which has not been filtered, into the reader, accumulating the image - fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult { - self.layers_reader.read_block(headers, block) - } - - /// Deliver the complete accumulated image - fn into_image(self) -> Image<L::Layers> { - Image { - attributes: self.image_attributes, - layer_data: self.layers_reader.into_layers() - } - } -} - - -/// A template that creates a `LayerReader` for each layer in the file. -pub trait ReadLayers<'s> { - - /// The type of the resulting Layers - type Layers; - - /// The type of the temporary layer reader - type Reader: LayersReader<Layers = Self::Layers>; - - /// Create a single reader for a single layer - fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader>; - - /// Specify that all attributes should be read from an image. - /// Use `from_file(path)` on the return value of this method to actually decode an image. - fn all_attributes(self) -> ReadImage<fn(f64), Self> where Self: Sized { - ReadImage::new(self, ignore_progress) - } -} - -/// Processes pixel blocks from a file and accumulates them into a single image layer. -pub trait LayersReader { - - /// The type of resulting layers - type Layers; - - /// Specify whether a single block of pixels should be loaded from the file - fn filter_block(&self, meta: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool; - - /// Load a single pixel block, which has not been filtered, into the reader, accumulating the layer - fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult; - - /// Deliver the final accumulated layers for the image - fn into_layers(self) -> Self::Layers; -} - diff --git a/vendor/exr/src/image/read/layers.rs b/vendor/exr/src/image/read/layers.rs deleted file mode 100644 index 75159c2..0000000 --- a/vendor/exr/src/image/read/layers.rs +++ /dev/null @@ -1,204 +0,0 @@ -//! How to read either a single or a list of layers. - -use crate::image::*; -use crate::meta::header::{Header, LayerAttributes}; -use crate::error::{Result, UnitResult, Error}; -use crate::block::{UncompressedBlock, BlockIndex}; -use crate::math::Vec2; -use crate::image::read::image::{ReadLayers, LayersReader}; -use crate::block::chunk::TileCoordinates; -use crate::meta::MetaData; - -/// Specify to read all channels, aborting if any one is invalid. -/// [`ReadRgbaChannels`] or [`ReadAnyChannels<ReadFlatSamples>`]. -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct ReadAllLayers<ReadChannels> { - - /// The channel reading specification - pub read_channels: ReadChannels, -} - -/// Specify to read only the first layer which meets the previously specified requirements -// FIXME do not throw error on deep data but just skip it! -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct ReadFirstValidLayer<ReadChannels> { - - /// The channel reading specification - pub read_channels: ReadChannels, -} - -/// A template that creates a [`ChannelsReader`] once for all channels per layer. -pub trait ReadChannels<'s> { - - /// The type of the temporary channels reader - type Reader: ChannelsReader; - - /// Create a single reader for all channels of a specific layer - fn create_channels_reader(&'s self, header: &Header) -> Result<Self::Reader>; - - - /// Read only the first layer which meets the previously specified requirements - /// For example, skips layers with deep data, if specified earlier. - /// Aborts if the image contains no layers. - // TODO test if this filters non-deep layers while ignoring deep data layers! - fn first_valid_layer(self) -> ReadFirstValidLayer<Self> where Self:Sized { ReadFirstValidLayer { read_channels: self } } - -// FIXME do not throw error on deep data but just skip it! - - - /// Reads all layers, including an empty list. Aborts if any of the layers are invalid, - /// even if only one of the layers contains unexpected data. - fn all_layers(self) -> ReadAllLayers<Self> where Self:Sized { ReadAllLayers { read_channels: self } } - - // TODO pub fn all_valid_layers(self) -> ReadAllValidLayers<Self> { ReadAllValidLayers { read_channels: self } } -} - - -/// Processes pixel blocks from a file and accumulates them into a list of layers. -/// For example, `ChannelsReader` can be -/// [`SpecificChannelsReader`] or [`AnyChannelsReader<FlatSamplesReader>`]. -#[derive(Debug, Clone, PartialEq)] -pub struct AllLayersReader<ChannelsReader> { - layer_readers: SmallVec<[LayerReader<ChannelsReader>; 2]>, // TODO unpack struct? -} - -/// Processes pixel blocks from a file and accumulates them into a single layers, using only the first. -/// For example, `ChannelsReader` can be -/// `SpecificChannelsReader` or `AnyChannelsReader<FlatSamplesReader>`. -#[derive(Debug, Clone, PartialEq)] -pub struct FirstValidLayerReader<ChannelsReader> { - layer_reader: LayerReader<ChannelsReader>, - layer_index: usize, -} - -/// Processes pixel blocks from a file and accumulates them into a single layers. -/// For example, `ChannelsReader` can be -/// `SpecificChannelsReader` or `AnyChannelsReader<FlatSamplesReader>`. -#[derive(Debug, Clone, PartialEq)] -pub struct LayerReader<ChannelsReader> { - channels_reader: ChannelsReader, - attributes: LayerAttributes, - size: Vec2<usize>, - encoding: Encoding -} - -/// Processes pixel blocks from a file and accumulates them into multiple channels per layer. -pub trait ChannelsReader { - - /// The type of the resulting channel collection - type Channels; - - /// Specify whether a single block of pixels should be loaded from the file - fn filter_block(&self, tile: TileCoordinates) -> bool; - - /// Load a single pixel block, which has not been filtered, into the reader, accumulating the channel data - fn read_block(&mut self, header: &Header, block: UncompressedBlock) -> UnitResult; - - /// Deliver the final accumulated channel collection for the image - fn into_channels(self) -> Self::Channels; -} - - -impl<C> LayerReader<C> { - fn new(header: &Header, channels_reader: C) -> Result<Self> { - Ok(LayerReader { - channels_reader, - attributes: header.own_attributes.clone(), - size: header.layer_size, - encoding: Encoding { - compression: header.compression, - line_order: header.line_order, - blocks: match header.blocks { - crate::meta::BlockDescription::ScanLines => Blocks::ScanLines, - crate::meta::BlockDescription::Tiles(TileDescription { tile_size, .. }) => Blocks::Tiles(tile_size) - }, - }, - }) - } -} - -impl<'s, C> ReadLayers<'s> for ReadAllLayers<C> where C: ReadChannels<'s> { - type Layers = Layers<<C::Reader as ChannelsReader>::Channels>; - type Reader = AllLayersReader<C::Reader>; - - fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader> { - let readers: Result<_> = headers.iter() - .map(|header| LayerReader::new(header, self.read_channels.create_channels_reader(header)?)) - .collect(); - - Ok(AllLayersReader { - layer_readers: readers? - }) - } -} - -impl<C> LayersReader for AllLayersReader<C> where C: ChannelsReader { - type Layers = Layers<C::Channels>; - - fn filter_block(&self, _: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool { - let layer = self.layer_readers.get(block.layer).expect("invalid layer index argument"); - layer.channels_reader.filter_block(tile) - } - - fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult { - self.layer_readers - .get_mut(block.index.layer).expect("invalid layer index argument") - .channels_reader.read_block(headers.get(block.index.layer).expect("invalid header index in block"), block) - } - - fn into_layers(self) -> Self::Layers { - self.layer_readers - .into_iter() - .map(|layer| Layer { - channel_data: layer.channels_reader.into_channels(), - attributes: layer.attributes, - size: layer.size, - encoding: layer.encoding - }) - .collect() - } -} - - -impl<'s, C> ReadLayers<'s> for ReadFirstValidLayer<C> where C: ReadChannels<'s> { - type Layers = Layer<<C::Reader as ChannelsReader>::Channels>; - type Reader = FirstValidLayerReader<C::Reader>; - - fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader> { - headers.iter().enumerate() - .flat_map(|(index, header)| - self.read_channels.create_channels_reader(header) - .and_then(|reader| Ok(FirstValidLayerReader { - layer_reader: LayerReader::new(header, reader)?, - layer_index: index - })) - .ok() - ) - .next() - .ok_or(Error::invalid("no layer in the image matched your specified requirements")) - } -} - - -impl<C> LayersReader for FirstValidLayerReader<C> where C: ChannelsReader { - type Layers = Layer<C::Channels>; - - fn filter_block(&self, _: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool { - block.layer == self.layer_index && self.layer_reader.channels_reader.filter_block(tile) - } - - fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult { - debug_assert_eq!(block.index.layer, self.layer_index, "block should have been filtered out"); - self.layer_reader.channels_reader.read_block(&headers[self.layer_index], block) - } - - fn into_layers(self) -> Self::Layers { - Layer { - channel_data: self.layer_reader.channels_reader.into_channels(), - attributes: self.layer_reader.attributes, - size: self.layer_reader.size, - encoding: self.layer_reader.encoding - } - } -} - diff --git a/vendor/exr/src/image/read/levels.rs b/vendor/exr/src/image/read/levels.rs deleted file mode 100644 index 5705903..0000000 --- a/vendor/exr/src/image/read/levels.rs +++ /dev/null @@ -1,219 +0,0 @@ -//! 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(), - } - }, - } - } -} diff --git a/vendor/exr/src/image/read/mod.rs b/vendor/exr/src/image/read/mod.rs deleted file mode 100644 index c03fc90..0000000 --- a/vendor/exr/src/image/read/mod.rs +++ /dev/null @@ -1,207 +0,0 @@ - -//! Read an exr image. -//! -//! For great flexibility and customization, use the `read()` function. -//! The return value of the `read()` function must be further customized before reading a file. - -//! -//! For very simple applications, you can alternatively use one of these functions: -//! -//! 1. `read_first_rgba_layer_from_file(path, your_constructor, your_pixel_setter)`: -//! You specify how to store the pixels. -//! The first layer containing rgba channels is then loaded from the file. -//! Fails if no rgba layer can be found. -//! -//! 1. `read_all_rgba_layers_from_file(path, your_constructor, your_pixel_setter)`: -//! You specify how to store the pixels. -//! All layers containing rgba channels are then loaded from the file. -//! Fails if any layer in the image does not contain rgba channels. -//! -//! 1. `read_first_flat_layer_from_file(path)`: -//! The first layer containing non-deep data with arbitrary channels is loaded from the file. -//! Fails if no non-deep layer can be found. -//! -//! 1. `read_all_flat_layers_from_file(path)`: -//! All layers containing non-deep data with arbitrary channels are loaded from the file. -//! Fails if any layer in the image contains deep data. -//! -//! 1. `read_all_data_from_file(path)`: -//! All layers with arbitrary channels and all resolution levels are extracted from the file. -//! -//! Note: Currently does not support deep data, and currently fails -//! if any layer in the image contains deep data. -//! - -// The following three stages are internally used to read an image. -// 1. `ReadImage` - The specification. Contains everything the user wants to tell us about loading an image. -// The data in this structure will be instantiated and might be borrowed. -// 2. `ImageReader` - The temporary reader. Based on the specification of the blueprint, -// a reader is instantiated, once for each layer. -// This data structure accumulates the image data from the file. -// It also owns temporary data and references the blueprint. -// 3. `Image` - The clean image. The accumulated data from the Reader -// is converted to the clean image structure, without temporary data. - -pub mod image; -pub mod layers; -pub mod any_channels; -pub mod levels; -pub mod samples; -pub mod specific_channels; - -use crate::error::{Result}; -use crate::image::read::samples::{ReadFlatSamples}; -use std::path::Path; -use crate::image::{AnyImage, AnyChannels, FlatSamples, Image, Layer, FlatImage, PixelLayersImage, RgbaChannels}; -use crate::image::read::image::ReadLayers; -use crate::image::read::layers::ReadChannels; -use crate::math::Vec2; -use crate::prelude::{PixelImage}; -use crate::block::samples::FromNativeSample; - - -/// All resolution levels, all channels, all layers. -/// Does not support deep data yet. Uses parallel decompression and relaxed error handling. -/// Inspect the source code of this function if you need customization. -pub fn read_all_data_from_file(path: impl AsRef<Path>) -> Result<AnyImage> { - read() - .no_deep_data() // TODO deep data - .all_resolution_levels() - .all_channels() - .all_layers() - .all_attributes() - .from_file(path) -} - -// FIXME do not throw error on deep data but just skip it! -/// No deep data, no resolution levels, all channels, all layers. -/// Uses parallel decompression and relaxed error handling. -/// Inspect the source code of this function if you need customization. -pub fn read_all_flat_layers_from_file(path: impl AsRef<Path>) -> Result<FlatImage> { - read() - .no_deep_data() - .largest_resolution_level() - .all_channels() - .all_layers() - .all_attributes() - .from_file(path) -} - -/// No deep data, no resolution levels, all channels, first layer. -/// Uses parallel decompression and relaxed error handling. -/// Inspect the source code of this function if you need customization. -pub fn read_first_flat_layer_from_file(path: impl AsRef<Path>) -> Result<Image<Layer<AnyChannels<FlatSamples>>>> { - read() - .no_deep_data() - .largest_resolution_level() - .all_channels() - .first_valid_layer() - .all_attributes() - .from_file(path) -} - -/// No deep data, no resolution levels, rgba channels, all layers. -/// If a single layer does not contain rgba data, this method returns an error. -/// Uses parallel decompression and relaxed error handling. -/// `Create` and `Set` can be closures, see the examples for more information. -/// Inspect the source code of this function if you need customization. -/// 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`. -// FIXME Set and Create should not need to be static -pub fn read_all_rgba_layers_from_file<R,G,B,A, Set:'static, Create:'static, Pixels: 'static>( - path: impl AsRef<Path>, create: Create, set_pixel: Set -) - -> Result<PixelLayersImage<Pixels, RgbaChannels>> - where - R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample, - Create: Fn(Vec2<usize>, &RgbaChannels) -> Pixels, // TODO type alias? CreateRgbaPixels<Pixels=Pixels>, - Set: Fn(&mut Pixels, Vec2<usize>, (R,G,B,A)), -{ - read() - .no_deep_data() - .largest_resolution_level() - .rgba_channels(create, set_pixel) - .all_layers() - .all_attributes() - .from_file(path) -} - -/// No deep data, no resolution levels, rgba channels, choosing the first layer with rgba channels. -/// Uses parallel decompression and relaxed error handling. -/// `Create` and `Set` can be closures, see the examples for more information. -/// Inspect the source code of this function if you need customization. -/// 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`. -// FIXME Set and Create should not need to be static -pub fn read_first_rgba_layer_from_file<R,G,B,A, Set:'static, Create:'static, Pixels: 'static>( - path: impl AsRef<Path>, create: Create, set_pixel: Set -) - -> Result<PixelImage<Pixels, RgbaChannels>> - where - R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample, - Create: Fn(Vec2<usize>, &RgbaChannels) -> Pixels, // TODO type alias? CreateRgbaPixels<Pixels=Pixels>, - Set: Fn(&mut Pixels, Vec2<usize>, (R,G,B,A)), -{ - read() - .no_deep_data() - .largest_resolution_level() - .rgba_channels(create, set_pixel) - .first_valid_layer() - .all_attributes() - .from_file(path) -} - - -/// Utilizes the builder pattern to configure an image reader. This is the initial struct. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct ReadBuilder; - -/// Create a reader which can be used to load an exr image. -/// Allows you to exactly specify how to load the image, for example: -/// -/// ```no_run -/// use exr::prelude::*; -/// -/// // the type of the this image depends on the chosen options -/// let image = read() -/// .no_deep_data() // (currently required) -/// .largest_resolution_level() // or `all_resolution_levels()` -/// .all_channels() // or `rgba_channels(constructor, setter)` -/// .all_layers() // or `first_valid_layer()` -/// .all_attributes() // (currently required) -/// .on_progress(|progress| println!("progress: {:.1}", progress*100.0)) // optional -/// .from_file("image.exr").unwrap(); // or `from_buffered(my_byte_slice)` -/// ``` -/// -/// You can alternatively use one of the following simpler functions: -/// 1. `read_first_flat_layer_from_file` -/// 1. `read_all_rgba_layers_from_file` -/// 1. `read_all_flat_layers_from_file` -/// 1. `read_all_data_from_file` -/// -// TODO not panic but skip deep layers! -pub fn read() -> ReadBuilder { ReadBuilder } - -impl ReadBuilder { - - /// Specify to handle only one sample per channel, disabling "deep data". - // TODO not panic but skip deep layers! - pub fn no_deep_data(self) -> ReadFlatSamples { ReadFlatSamples } - - // pub fn any_resolution_levels() -> ReadBuilder<> {} - - // TODO - // e. g. `let sum = reader.any_channels_with(|sample, sum| sum += sample)` - // e. g. `let floats = reader.any_channels_with(|sample, f32_samples| f32_samples[index] = sample as f32)` - // pub fn no_deep_data_with <S> (self, storage: S) -> FlatSamplesWith<S> { } - - // pub fn flat_and_deep_data(self) -> ReadAnySamples { ReadAnySamples } -} diff --git a/vendor/exr/src/image/read/samples.rs b/vendor/exr/src/image/read/samples.rs deleted file mode 100644 index e03c3cc..0000000 --- a/vendor/exr/src/image/read/samples.rs +++ /dev/null @@ -1,122 +0,0 @@ -//! How to read samples (a grid of `f32`, `f16` or `u32` values). - -use crate::image::*; -use crate::meta::header::{Header}; -use crate::error::{Result, UnitResult}; -use crate::block::lines::LineRef; -use crate::math::Vec2; -use crate::meta::attribute::{ChannelDescription, SampleType}; -use crate::image::read::any_channels::{SamplesReader, ReadSamples}; -use crate::image::read::levels::{ReadSamplesLevel, ReadAllLevels, ReadLargestLevel}; -use crate::block::chunk::TileCoordinates; -// use crate::image::read::layers::ReadChannels; - -/// Specify to read only flat samples and no "deep data" -// FIXME do not throw error on deep data but just skip it! -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct ReadFlatSamples; -// pub struct ReadAnySamples; - -impl ReadFlatSamples { - - // TODO - // e. g. `let sum = reader.any_channels_with(|sample, sum| sum += sample)` - // pub fn any_channels_with <S> (self, storage: S) -> { } - - /// Specify to read only the highest resolution level, skipping all smaller variations. - pub fn largest_resolution_level(self) -> ReadLargestLevel<Self> { ReadLargestLevel { read_samples: self } } - - /// Specify to read all contained resolution levels from the image, if any. - pub fn all_resolution_levels(self) -> ReadAllLevels<Self> { ReadAllLevels { read_samples: self } } - - // TODO pub fn specific_resolution_level<F: Fn(&[Vec2<usize>])->usize >(self, select_level: F) -> ReadLevelBy<Self> { ReadAllLevels { read_samples: self } } -} - - -/*pub struct AnySamplesReader { TODO - resolution: Vec2<usize>, - samples: DeepAndFlatSamples -}*/ - -/// Processes pixel blocks from a file and accumulates them into a grid of samples, for example "Red" or "Alpha". -#[derive(Debug, Clone, PartialEq)] -pub struct FlatSamplesReader { - level: Vec2<usize>, - resolution: Vec2<usize>, - samples: FlatSamples -} - - -// only used when samples is directly inside a channel, without levels -impl ReadSamples for ReadFlatSamples { - type Reader = FlatSamplesReader; - - fn create_sample_reader(&self, header: &Header, channel: &ChannelDescription) -> Result<Self::Reader> { - self.create_samples_level_reader(header, channel, Vec2(0, 0), header.layer_size) - } -} - -impl ReadSamplesLevel for ReadFlatSamples { - type Reader = FlatSamplesReader; - - fn create_samples_level_reader(&self, _header: &Header, channel: &ChannelDescription, level: Vec2<usize>, resolution: Vec2<usize>) -> Result<Self::Reader> { - Ok(FlatSamplesReader { - level, resolution, // TODO sampling - samples: match channel.sample_type { - SampleType::F16 => FlatSamples::F16(vec![f16::ZERO; resolution.area()]), - SampleType::F32 => FlatSamples::F32(vec![0.0; resolution.area()]), - SampleType::U32 => FlatSamples::U32(vec![0; resolution.area()]), - } - }) - } -} - - -impl SamplesReader for FlatSamplesReader { - type Samples = FlatSamples; - - fn filter_block(&self, tile: TileCoordinates) -> bool { - tile.level_index == self.level - } - - fn read_line(&mut self, line: LineRef<'_>) -> UnitResult { - let index = line.location; - let resolution = self.resolution; - - // the index is generated by ourselves and must always be correct - debug_assert_eq!(index.level, self.level, "line should have been filtered"); - debug_assert!(index.position.x() + index.sample_count <= resolution.width(), "line index calculation bug"); - debug_assert!(index.position.y() < resolution.height(), "line index calculation bug"); - debug_assert_ne!(resolution.0, 0, "sample size bug"); - - let start_index = index.position.y() * resolution.width() + index.position.x(); - let end_index = start_index + index.sample_count; - - debug_assert!( - start_index < end_index && end_index <= self.samples.len(), - "for resolution {:?}, this is an invalid line: {:?}", - self.resolution, line.location - ); - - match &mut self.samples { - FlatSamples::F16(samples) => - line.read_samples_into_slice(&mut samples[start_index .. end_index]) - .expect("writing line bytes failed"), - - FlatSamples::F32(samples) => - line.read_samples_into_slice(&mut samples[start_index .. end_index]) - .expect("writing line bytes failed"), - - FlatSamples::U32(samples) => - line.read_samples_into_slice(&mut samples[start_index .. end_index]) - .expect("writing line bytes failed"), - } - - Ok(()) - } - - fn into_samples(self) -> FlatSamples { - self.samples - } -} - diff --git a/vendor/exr/src/image/read/specific_channels.rs b/vendor/exr/src/image/read/specific_channels.rs deleted file mode 100644 index 375691c..0000000 --- a/vendor/exr/src/image/read/specific_channels.rs +++ /dev/null @@ -1,463 +0,0 @@ -//! How to read arbitrary but specific selection of arbitrary channels. -//! This is not a zero-cost abstraction. - -use crate::image::recursive::*; -use crate::block::samples::*; -use crate::image::*; -use crate::math::*; -use crate::meta::header::*; -use crate::error::*; -use crate::block::UncompressedBlock; -use crate::image::read::layers::{ChannelsReader, ReadChannels}; -use crate::block::chunk::TileCoordinates; - -use std::marker::PhantomData; -use crate::io::Read; - - -/// Can be attached one more channel reader. -/// Call `required` or `optional` on this object to declare another channel to be read from the file. -/// Call `collect_pixels` at last to define how the previously declared pixels should be stored. -pub trait ReadSpecificChannel: Sized + CheckDuplicates { - - /// A separate internal reader for the pixels. Will be of type `Recursive<_, SampleReader<_>>`, - /// depending on the pixels of the specific channel combination. - type RecursivePixelReader: RecursivePixelReader; - - /// Create a separate internal reader for the pixels of the specific channel combination. - fn create_recursive_reader(&self, channels: &ChannelList) -> Result<Self::RecursivePixelReader>; - - /// Plan to read an additional channel from the image, with the specified name. - /// If the channel cannot be found in the image when the image is read, the image will not be loaded. - /// The generic parameter can usually be inferred from the closure in `collect_pixels`. - fn required<Sample>(self, channel_name: impl Into<Text>) -> ReadRequiredChannel<Self, Sample> { - let channel_name = channel_name.into(); - assert!(self.already_contains(&channel_name).not(), "a channel with the name `{}` is already defined", channel_name); - ReadRequiredChannel { channel_name, previous_channels: self, px: Default::default() } - } - - /// Plan to read an additional channel from the image, with the specified name. - /// If the file does not contain this channel, the specified default sample will be returned instead. - /// You can check whether the channel has been loaded by - /// checking the presence of the optional channel description before instantiating your own image. - /// The generic parameter can usually be inferred from the closure in `collect_pixels`. - fn optional<Sample>(self, channel_name: impl Into<Text>, default_sample: Sample) - -> ReadOptionalChannel<Self, Sample> - { - let channel_name = channel_name.into(); - assert!(self.already_contains(&channel_name).not(), "a channel with the name `{}` is already defined", channel_name); - ReadOptionalChannel { channel_name, previous_channels: self, default_sample } - } - - /// 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 `f16`, `f32`, `u32` or `Sample` values. - /// See the examples for more information. - fn collect_pixels<Pixel, PixelStorage, CreatePixels, SetPixel>( - self, create_pixels: CreatePixels, set_pixel: SetPixel - ) -> CollectPixels<Self, Pixel, PixelStorage, CreatePixels, SetPixel> - where - <Self::RecursivePixelReader as RecursivePixelReader>::RecursivePixel: IntoTuple<Pixel>, - <Self::RecursivePixelReader as RecursivePixelReader>::RecursiveChannelDescriptions: IntoNonRecursive, - CreatePixels: Fn( - Vec2<usize>, - &<<Self::RecursivePixelReader as RecursivePixelReader>::RecursiveChannelDescriptions as IntoNonRecursive>::NonRecursive - ) -> PixelStorage, - SetPixel: Fn(&mut PixelStorage, Vec2<usize>, Pixel), - { - CollectPixels { read_channels: self, set_pixel, create_pixels, px: Default::default() } - } -} - -/// A reader containing sub-readers for reading the pixel content of an image. -pub trait RecursivePixelReader { - - /// The channel descriptions from the image. - /// Will be converted to a tuple before being stored in `SpecificChannels<_, ChannelDescriptions>`. - type RecursiveChannelDescriptions; - - /// Returns the channel descriptions based on the channels in the file. - fn get_descriptions(&self) -> Self::RecursiveChannelDescriptions; - - /// The pixel type. Will be converted to a tuple at the end of the process. - type RecursivePixel: Copy + Default + 'static; - - /// Read the line of pixels. - fn read_pixels<'s, FullPixel>( - &self, bytes: &'s[u8], pixels: &mut [FullPixel], - get_pixel: impl Fn(&mut FullPixel) -> &mut Self::RecursivePixel - ); -} - -// does not use the generic `Recursive` struct to reduce the number of angle brackets in the public api -/// Used to read another specific channel from an image. -/// Contains the previous `ReadChannels` objects. -#[derive(Clone, Debug)] -pub struct ReadOptionalChannel<ReadChannels, Sample> { - previous_channels: ReadChannels, - channel_name: Text, - default_sample: Sample, -} - -// does not use the generic `Recursive` struct to reduce the number of angle brackets in the public api -/// Used to read another specific channel from an image. -/// Contains the previous `ReadChannels` objects. -#[derive(Clone, Debug)] -pub struct ReadRequiredChannel<ReadChannels, Sample> { - previous_channels: ReadChannels, - channel_name: Text, - px: PhantomData<Sample>, -} - -/// Specifies how to collect all the specified channels into a number of individual pixels. -#[derive(Copy, Clone, Debug)] -pub struct CollectPixels<ReadChannels, Pixel, PixelStorage, CreatePixels, SetPixel> { - read_channels: ReadChannels, - create_pixels: CreatePixels, - set_pixel: SetPixel, - px: PhantomData<(Pixel, PixelStorage)>, -} - -impl<Inner: CheckDuplicates, Sample> CheckDuplicates for ReadRequiredChannel<Inner, Sample> { - fn already_contains(&self, name: &Text) -> bool { - &self.channel_name == name || self.previous_channels.already_contains(name) - } -} - -impl<Inner: CheckDuplicates, Sample> CheckDuplicates for ReadOptionalChannel<Inner, Sample> { - fn already_contains(&self, name: &Text) -> bool { - &self.channel_name == name || self.previous_channels.already_contains(name) - } -} - -impl<'s, InnerChannels, Pixel, PixelStorage, CreatePixels, SetPixel: 's> -ReadChannels<'s> for CollectPixels<InnerChannels, Pixel, PixelStorage, CreatePixels, SetPixel> - where - InnerChannels: ReadSpecificChannel, - <InnerChannels::RecursivePixelReader as RecursivePixelReader>::RecursivePixel: IntoTuple<Pixel>, - <InnerChannels::RecursivePixelReader as RecursivePixelReader>::RecursiveChannelDescriptions: IntoNonRecursive, - CreatePixels: Fn(Vec2<usize>, &<<InnerChannels::RecursivePixelReader as RecursivePixelReader>::RecursiveChannelDescriptions as IntoNonRecursive>::NonRecursive) -> PixelStorage, - SetPixel: Fn(&mut PixelStorage, Vec2<usize>, Pixel), -{ - type Reader = SpecificChannelsReader< - PixelStorage, &'s SetPixel, - InnerChannels::RecursivePixelReader, - Pixel, - >; - - fn create_channels_reader(&'s self, header: &Header) -> Result<Self::Reader> { - if header.deep { return Err(Error::invalid("`SpecificChannels` does not support deep data yet")) } - - let pixel_reader = self.read_channels.create_recursive_reader(&header.channels)?; - let channel_descriptions = pixel_reader.get_descriptions().into_non_recursive();// TODO not call this twice - - let create = &self.create_pixels; - let pixel_storage = create(header.layer_size, &channel_descriptions); - - Ok(SpecificChannelsReader { - set_pixel: &self.set_pixel, - pixel_storage, - pixel_reader, - px: Default::default() - }) - } -} - -/// The reader that holds the temporary data that is required to read some specified channels. -#[derive(Copy, Clone, Debug)] -pub struct SpecificChannelsReader<PixelStorage, SetPixel, PixelReader, Pixel> { - set_pixel: SetPixel, - pixel_storage: PixelStorage, - pixel_reader: PixelReader, - px: PhantomData<Pixel> -} - -impl<PixelStorage, SetPixel, PxReader, Pixel> -ChannelsReader for SpecificChannelsReader<PixelStorage, SetPixel, PxReader, Pixel> - where PxReader: RecursivePixelReader, - PxReader::RecursivePixel: IntoTuple<Pixel>, - PxReader::RecursiveChannelDescriptions: IntoNonRecursive, - SetPixel: Fn(&mut PixelStorage, Vec2<usize>, Pixel), -{ - type Channels = SpecificChannels<PixelStorage, <PxReader::RecursiveChannelDescriptions as IntoNonRecursive>::NonRecursive>; - - fn filter_block(&self, tile: TileCoordinates) -> bool { tile.is_largest_resolution_level() } // TODO all levels - - fn read_block(&mut self, header: &Header, block: UncompressedBlock) -> UnitResult { - let mut pixels = vec![PxReader::RecursivePixel::default(); block.index.pixel_size.width()]; // TODO allocate once in self - - let byte_lines = block.data.chunks_exact(header.channels.bytes_per_pixel * block.index.pixel_size.width()); - debug_assert_eq!(byte_lines.len(), block.index.pixel_size.height(), "invalid block lines split"); - - for (y_offset, line_bytes) in byte_lines.enumerate() { // TODO sampling - // this two-step copy method should be very cache friendly in theory, and also reduce sample_type lookup count - self.pixel_reader.read_pixels(line_bytes, &mut pixels, |px| px); - - for (x_offset, pixel) in pixels.iter().enumerate() { - let set_pixel = &self.set_pixel; - set_pixel(&mut self.pixel_storage, block.index.pixel_position + Vec2(x_offset, y_offset), pixel.into_tuple()); - } - } - - Ok(()) - } - - fn into_channels(self) -> Self::Channels { - SpecificChannels { channels: self.pixel_reader.get_descriptions().into_non_recursive(), pixels: self.pixel_storage } - } -} - - -/// Read zero channels from an image. Call `with_named_channel` on this object -/// to read as many channels as desired. -pub type ReadZeroChannels = NoneMore; - -impl ReadSpecificChannel for NoneMore { - type RecursivePixelReader = NoneMore; - fn create_recursive_reader(&self, _: &ChannelList) -> Result<Self::RecursivePixelReader> { Ok(NoneMore) } -} - -impl<DefaultSample, ReadChannels> ReadSpecificChannel for ReadOptionalChannel<ReadChannels, DefaultSample> - where ReadChannels: ReadSpecificChannel, DefaultSample: FromNativeSample + 'static, -{ - type RecursivePixelReader = Recursive<ReadChannels::RecursivePixelReader, OptionalSampleReader<DefaultSample>>; - - fn create_recursive_reader(&self, channels: &ChannelList) -> Result<Self::RecursivePixelReader> { - debug_assert!(self.previous_channels.already_contains(&self.channel_name).not(), "duplicate channel name: {}", self.channel_name); - - let inner_samples_reader = self.previous_channels.create_recursive_reader(channels)?; - let reader = channels.channels_with_byte_offset() - .find(|(_, channel)| channel.name == self.channel_name) - .map(|(channel_byte_offset, channel)| SampleReader { - channel_byte_offset, channel: channel.clone(), - px: Default::default() - }); - - Ok(Recursive::new(inner_samples_reader, OptionalSampleReader { - reader, default_sample: self.default_sample, - })) - } -} - -impl<Sample, ReadChannels> ReadSpecificChannel for ReadRequiredChannel<ReadChannels, Sample> - where ReadChannels: ReadSpecificChannel, Sample: FromNativeSample + 'static -{ - type RecursivePixelReader = Recursive<ReadChannels::RecursivePixelReader, SampleReader<Sample>>; - - fn create_recursive_reader(&self, channels: &ChannelList) -> Result<Self::RecursivePixelReader> { - let previous_samples_reader = self.previous_channels.create_recursive_reader(channels)?; - let (channel_byte_offset, channel) = channels.channels_with_byte_offset() - .find(|(_, channel)| channel.name == self.channel_name) - .ok_or_else(|| Error::invalid(format!( - "layer does not contain all of your specified channels (`{}` is missing)", - self.channel_name - )))?; - - Ok(Recursive::new(previous_samples_reader, SampleReader { channel_byte_offset, channel: channel.clone(), px: Default::default() })) - } -} - -/// Reader for a single channel. Generic over the concrete sample type (f16, f32, u32). -#[derive(Clone, Debug)] -pub struct SampleReader<Sample> { - - /// to be multiplied with line width! - channel_byte_offset: usize, - - channel: ChannelDescription, - px: PhantomData<Sample> -} - -/// Reader for a single channel. Generic over the concrete sample type (f16, f32, u32). -/// Can also skip reading a channel if it could not be found in the image. -#[derive(Clone, Debug)] -pub struct OptionalSampleReader<DefaultSample> { - reader: Option<SampleReader<DefaultSample>>, - default_sample: DefaultSample, -} - -impl<Sample: FromNativeSample> SampleReader<Sample> { - fn read_own_samples<'s, FullPixel>( - &self, bytes: &'s[u8], pixels: &mut [FullPixel], - get_sample: impl Fn(&mut FullPixel) -> &mut Sample - ){ - let start_index = pixels.len() * self.channel_byte_offset; - let byte_count = pixels.len() * self.channel.sample_type.bytes_per_sample(); - let mut own_bytes_reader = &mut &bytes[start_index .. start_index + byte_count]; // TODO check block size somewhere - let mut samples_out = pixels.iter_mut().map(|pixel| get_sample(pixel)); - - // match the type once for the whole line, not on every single sample - match self.channel.sample_type { - SampleType::F16 => read_and_convert_all_samples_batched( - &mut own_bytes_reader, &mut samples_out, - Sample::from_f16s - ), - - SampleType::F32 => read_and_convert_all_samples_batched( - &mut own_bytes_reader, &mut samples_out, - Sample::from_f32s - ), - - SampleType::U32 => read_and_convert_all_samples_batched( - &mut own_bytes_reader, &mut samples_out, - Sample::from_u32s - ), - } - - debug_assert!(samples_out.next().is_none(), "not all samples have been converted"); - debug_assert!(own_bytes_reader.is_empty(), "bytes left after reading all samples"); - } -} - - -/// Does the same as `convert_batch(in_bytes.chunks().map(From::from_bytes))`, but vectorized. -/// Reads the samples for one line, using the sample type specified in the file, -/// and then converts those to the desired sample types. -/// Uses batches to allow vectorization, converting multiple values with one instruction. -fn read_and_convert_all_samples_batched<'t, From, To>( - mut in_bytes: impl Read, - out_samples: &mut impl ExactSizeIterator<Item=&'t mut To>, - convert_batch: fn(&[From], &mut [To]) -) where From: Data + Default + Copy, To: 't + Default + Copy -{ - // this is not a global! why is this warning triggered? - #[allow(non_upper_case_globals)] - const batch_size: usize = 16; - - let total_sample_count = out_samples.len(); - let batch_count = total_sample_count / batch_size; - let remaining_samples_count = total_sample_count % batch_size; - - let len_error_msg = "sample count was miscalculated"; - let byte_error_msg = "error when reading from in-memory slice"; - - // write samples from a given slice to the output iterator. should be inlined. - let output_n_samples = &mut move |samples: &[To]| { - for converted_sample in samples { - *out_samples.next().expect(len_error_msg) = *converted_sample; - } - }; - - // read samples from the byte source into a given slice. should be inlined. - // todo: use #[inline] when available - // error[E0658]: attributes on expressions are experimental, - // see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information - let read_n_samples = &mut move |samples: &mut [From]| { - Data::read_slice(&mut in_bytes, samples).expect(byte_error_msg); - }; - - // temporary arrays with fixed size, operations should be vectorized within these arrays - let mut source_samples_batch: [From; batch_size] = Default::default(); - let mut desired_samples_batch: [To; batch_size] = Default::default(); - - // first convert all whole batches, size statically known to be 16 element arrays - for _ in 0 .. batch_count { - read_n_samples(&mut source_samples_batch); - convert_batch(source_samples_batch.as_slice(), desired_samples_batch.as_mut_slice()); - output_n_samples(&desired_samples_batch); - } - - // then convert a partial remaining batch, size known only at runtime - if remaining_samples_count != 0 { - let source_samples_batch = &mut source_samples_batch[..remaining_samples_count]; - let desired_samples_batch = &mut desired_samples_batch[..remaining_samples_count]; - - read_n_samples(source_samples_batch); - convert_batch(source_samples_batch, desired_samples_batch); - output_n_samples(desired_samples_batch); - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn equals_naive_f32(){ - for total_array_size in [3, 7, 30, 41, 120, 10_423] { - let input_f32s = (0..total_array_size).map(|_| rand::random::<f32>()).collect::<Vec<f32>>(); - let in_f32s_bytes = input_f32s.iter().cloned().flat_map(f32::to_le_bytes).collect::<Vec<u8>>(); - - let mut out_f16_samples_batched = vec![ - f16::from_f32(rand::random::<f32>()); - total_array_size - ]; - - read_and_convert_all_samples_batched( - &mut in_f32s_bytes.as_slice(), - &mut out_f16_samples_batched.iter_mut(), - f16::from_f32s - ); - - let out_f16_samples_naive = input_f32s.iter() - .cloned().map(f16::from_f32); - - assert!(out_f16_samples_naive.eq(out_f16_samples_batched)); - } - } -} - - -impl RecursivePixelReader for NoneMore { - type RecursiveChannelDescriptions = NoneMore; - fn get_descriptions(&self) -> Self::RecursiveChannelDescriptions { NoneMore } - - type RecursivePixel = NoneMore; - - fn read_pixels<'s, FullPixel>( - &self, _: &'s[u8], _: &mut [FullPixel], - _: impl Fn(&mut FullPixel) -> &mut NoneMore - ){} -} - -impl<Sample, InnerReader: RecursivePixelReader> - RecursivePixelReader - for Recursive<InnerReader, SampleReader<Sample>> - where Sample: FromNativeSample + 'static -{ - type RecursiveChannelDescriptions = Recursive<InnerReader::RecursiveChannelDescriptions, ChannelDescription>; - fn get_descriptions(&self) -> Self::RecursiveChannelDescriptions { Recursive::new(self.inner.get_descriptions(), self.value.channel.clone()) } - - type RecursivePixel = Recursive<InnerReader::RecursivePixel, Sample>; - - fn read_pixels<'s, FullPixel>( - &self, bytes: &'s[u8], pixels: &mut [FullPixel], - get_pixel: impl Fn(&mut FullPixel) -> &mut Self::RecursivePixel - ) { - self.value.read_own_samples(bytes, pixels, |px| &mut get_pixel(px).value); - self.inner.read_pixels(bytes, pixels, |px| &mut get_pixel(px).inner); - } -} - -impl<Sample, InnerReader: RecursivePixelReader> -RecursivePixelReader -for Recursive<InnerReader, OptionalSampleReader<Sample>> - where Sample: FromNativeSample + 'static -{ - type RecursiveChannelDescriptions = Recursive<InnerReader::RecursiveChannelDescriptions, Option<ChannelDescription>>; - fn get_descriptions(&self) -> Self::RecursiveChannelDescriptions { Recursive::new( - self.inner.get_descriptions(), self.value.reader.as_ref().map(|reader| reader.channel.clone()) - ) } - - type RecursivePixel = Recursive<InnerReader::RecursivePixel, Sample>; - - fn read_pixels<'s, FullPixel>( - &self, bytes: &'s[u8], pixels: &mut [FullPixel], - get_pixel: impl Fn(&mut FullPixel) -> &mut Self::RecursivePixel - ) { - if let Some(reader) = &self.value.reader { - reader.read_own_samples(bytes, pixels, |px| &mut get_pixel(px).value); - } - else { - // if this channel is optional and was not found in the file, fill the default sample - for pixel in pixels.iter_mut() { - get_pixel(pixel).value = self.value.default_sample; - } - } - - self.inner.read_pixels(bytes, pixels, |px| &mut get_pixel(px).inner); - } -} - - |