//! 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 (self, storage: S) -> { } /// Specify to read only the highest resolution level, skipping all smaller variations. pub fn largest_resolution_level(self) -> ReadLargestLevel { ReadLargestLevel { read_samples: self } } /// Specify to read all contained resolution levels from the image, if any. pub fn all_resolution_levels(self) -> ReadAllLevels { ReadAllLevels { read_samples: self } } // TODO pub fn specific_resolution_level])->usize >(self, select_level: F) -> ReadLevelBy { ReadAllLevels { read_samples: self } } } /*pub struct AnySamplesReader { TODO resolution: Vec2, 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, resolution: Vec2, 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.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, resolution: Vec2) -> Result { 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 } }