| 1 | //! How to read samples (a grid of `f32`, `f16` or `u32` values).
|
| 2 |
|
| 3 | use crate::image::*;
|
| 4 | use crate::meta::header::{Header};
|
| 5 | use crate::error::{Result, UnitResult};
|
| 6 | use crate::block::lines::LineRef;
|
| 7 | use crate::math::Vec2;
|
| 8 | use crate::meta::attribute::{ChannelDescription, SampleType};
|
| 9 | use crate::image::read::any_channels::{SamplesReader, ReadSamples};
|
| 10 | use crate::image::read::levels::{ReadSamplesLevel, ReadAllLevels, ReadLargestLevel};
|
| 11 | use crate::block::chunk::TileCoordinates;
|
| 12 | // use crate::image::read::layers::ReadChannels;
|
| 13 |
|
| 14 | /// Specify to read only flat samples and no "deep data"
|
| 15 | // FIXME do not throw error on deep data but just skip it!
|
| 16 | #[derive (Debug, Copy, Clone, Eq, PartialEq)]
|
| 17 | pub struct ReadFlatSamples;
|
| 18 | // pub struct ReadAnySamples;
|
| 19 |
|
| 20 | impl ReadFlatSamples {
|
| 21 |
|
| 22 | // TODO
|
| 23 | // e. g. `let sum = reader.any_channels_with(|sample, sum| sum += sample)`
|
| 24 | // pub fn any_channels_with <S> (self, storage: S) -> { }
|
| 25 |
|
| 26 | /// Specify to read only the highest resolution level, skipping all smaller variations.
|
| 27 | pub fn largest_resolution_level(self) -> ReadLargestLevel<Self> { ReadLargestLevel { read_samples: self } }
|
| 28 |
|
| 29 | /// Specify to read all contained resolution levels from the image, if any.
|
| 30 | pub fn all_resolution_levels(self) -> ReadAllLevels<Self> { ReadAllLevels { read_samples: self } }
|
| 31 |
|
| 32 | // TODO pub fn specific_resolution_level<F: Fn(&[Vec2<usize>])->usize >(self, select_level: F) -> ReadLevelBy<Self> { ReadAllLevels { read_samples: self } }
|
| 33 | }
|
| 34 |
|
| 35 |
|
| 36 | /*pub struct AnySamplesReader { TODO
|
| 37 | resolution: Vec2<usize>,
|
| 38 | samples: DeepAndFlatSamples
|
| 39 | }*/
|
| 40 |
|
| 41 | /// Processes pixel blocks from a file and accumulates them into a grid of samples, for example "Red" or "Alpha".
|
| 42 | #[derive (Debug, Clone, PartialEq)]
|
| 43 | pub struct FlatSamplesReader {
|
| 44 | level: Vec2<usize>,
|
| 45 | resolution: Vec2<usize>,
|
| 46 | samples: FlatSamples
|
| 47 | }
|
| 48 |
|
| 49 |
|
| 50 | // only used when samples is directly inside a channel, without levels
|
| 51 | impl ReadSamples for ReadFlatSamples {
|
| 52 | type Reader = FlatSamplesReader;
|
| 53 |
|
| 54 | fn create_sample_reader(&self, header: &Header, channel: &ChannelDescription) -> Result<Self::Reader> {
|
| 55 | self.create_samples_level_reader(header, channel, level:Vec2(0, 0), resolution:header.layer_size)
|
| 56 | }
|
| 57 | }
|
| 58 |
|
| 59 | impl ReadSamplesLevel for ReadFlatSamples {
|
| 60 | type Reader = FlatSamplesReader;
|
| 61 |
|
| 62 | fn create_samples_level_reader(&self, _header: &Header, channel: &ChannelDescription, level: Vec2<usize>, resolution: Vec2<usize>) -> Result<Self::Reader> {
|
| 63 | Ok(FlatSamplesReader {
|
| 64 | level, resolution, // TODO sampling
|
| 65 | samples: match channel.sample_type {
|
| 66 | SampleType::F16 => FlatSamples::F16(vec![f16::ZERO; resolution.area()]),
|
| 67 | SampleType::F32 => FlatSamples::F32(vec![0.0; resolution.area()]),
|
| 68 | SampleType::U32 => FlatSamples::U32(vec![0; resolution.area()]),
|
| 69 | }
|
| 70 | })
|
| 71 | }
|
| 72 | }
|
| 73 |
|
| 74 |
|
| 75 | impl SamplesReader for FlatSamplesReader {
|
| 76 | type Samples = FlatSamples;
|
| 77 |
|
| 78 | fn filter_block(&self, tile: TileCoordinates) -> bool {
|
| 79 | tile.level_index == self.level
|
| 80 | }
|
| 81 |
|
| 82 | fn read_line(&mut self, line: LineRef<'_>) -> UnitResult {
|
| 83 | let index = line.location;
|
| 84 | let resolution = self.resolution;
|
| 85 |
|
| 86 | // the index is generated by ourselves and must always be correct
|
| 87 | debug_assert_eq!(index.level, self.level, "line should have been filtered" );
|
| 88 | debug_assert!(index.position.x() + index.sample_count <= resolution.width(), "line index calculation bug" );
|
| 89 | debug_assert!(index.position.y() < resolution.height(), "line index calculation bug" );
|
| 90 | debug_assert_ne!(resolution.0, 0, "sample size bug" );
|
| 91 |
|
| 92 | let start_index = index.position.y() * resolution.width() + index.position.x();
|
| 93 | let end_index = start_index + index.sample_count;
|
| 94 |
|
| 95 | debug_assert!(
|
| 96 | start_index < end_index && end_index <= self.samples.len(),
|
| 97 | "for resolution {:?}, this is an invalid line: {:?}" ,
|
| 98 | self.resolution, line.location
|
| 99 | );
|
| 100 |
|
| 101 | match &mut self.samples {
|
| 102 | FlatSamples::F16(samples) =>
|
| 103 | line.read_samples_into_slice(&mut samples[start_index .. end_index])
|
| 104 | .expect("writing line bytes failed" ),
|
| 105 |
|
| 106 | FlatSamples::F32(samples) =>
|
| 107 | line.read_samples_into_slice(&mut samples[start_index .. end_index])
|
| 108 | .expect("writing line bytes failed" ),
|
| 109 |
|
| 110 | FlatSamples::U32(samples) =>
|
| 111 | line.read_samples_into_slice(&mut samples[start_index .. end_index])
|
| 112 | .expect("writing line bytes failed" ),
|
| 113 | }
|
| 114 |
|
| 115 | Ok(())
|
| 116 | }
|
| 117 |
|
| 118 | fn into_samples(self) -> FlatSamples {
|
| 119 | self.samples
|
| 120 | }
|
| 121 | }
|
| 122 |
|
| 123 | |