use crate::{
block::{chunk::TileCoordinates, lines::LineRef},
error::{Result, UnitResult},
image::{
read::{
any_channels::{ReadSamples, SamplesReader},
levels::{ReadAllLevels, ReadLargestLevel, ReadSamplesLevel},
},
*,
},
math::Vec2,
meta::{
attribute::{ChannelDescription, SampleType},
header::Header,
},
};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ReadFlatSamples;
impl ReadFlatSamples {
pub fn largest_resolution_level(self) -> ReadLargestLevel<Self> {
ReadLargestLevel {
read_samples: self,
}
}
pub fn all_resolution_levels(self) -> ReadAllLevels<Self> {
ReadAllLevels {
read_samples: self,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct FlatSamplesReader {
level: Vec2<usize>,
resolution: Vec2<usize>,
samples: FlatSamples,
}
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, 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;
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
}
}