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