diff options
Diffstat (limited to 'vendor/exr/src/image/read/any_channels.rs')
-rw-r--r-- | vendor/exr/src/image/read/any_channels.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/vendor/exr/src/image/read/any_channels.rs b/vendor/exr/src/image/read/any_channels.rs new file mode 100644 index 0000000..054a7c3 --- /dev/null +++ b/vendor/exr/src/image/read/any_channels.rs @@ -0,0 +1,128 @@ +//! 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() + } + } +} |