1//! How to read samples (a grid of `f32`, `f16` or `u32` values).
2
3use crate::image::*;
4use crate::meta::header::{Header};
5use crate::error::{Result, UnitResult};
6use crate::block::lines::LineRef;
7use crate::math::Vec2;
8use crate::meta::attribute::{ChannelDescription, SampleType};
9use crate::image::read::any_channels::{SamplesReader, ReadSamples};
10use crate::image::read::levels::{ReadSamplesLevel, ReadAllLevels, ReadLargestLevel};
11use 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)]
17pub struct ReadFlatSamples;
18// pub struct ReadAnySamples;
19
20impl 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)]
43pub 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
51impl 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
59impl 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
75impl 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