use crate::{
block::{chunk::TileCoordinates, lines::LineRef, samples::*},
error::*,
image::{
read::{any_channels::*, specific_channels::*},
recursive::*,
*,
},
math::Vec2,
meta::{attribute::*, header::Header, *},
};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ReadLargestLevel<DeepOrFlatSamples> {
pub read_samples: DeepOrFlatSamples,
}
impl<DeepOrFlatSamples> ReadLargestLevel<DeepOrFlatSamples> {
pub fn all_channels(self) -> ReadAnyChannels<DeepOrFlatSamples> {
ReadAnyChannels {
read_samples: self.read_samples,
}
}
pub fn rgba_channels<R, G, B, A, Create, Set, Pixels>(
self,
create_pixels: Create,
set_pixel: Set,
) -> CollectPixels<
ReadOptionalChannel<
ReadRequiredChannel<ReadRequiredChannel<ReadRequiredChannel<NoneMore, R>, G>, B>,
A,
>,
(R, G, B, A),
Pixels,
Create,
Set,
>
where
R: FromNativeSample,
G: FromNativeSample,
B: FromNativeSample,
A: FromNativeSample,
Create: Fn(Vec2<usize>, &RgbaChannels) -> Pixels,
Set: Fn(&mut Pixels, Vec2<usize>, (R, G, B, A)),
{
self.specific_channels()
.required("R")
.required("G")
.required("B")
.optional("A", A::from_f32(1.0))
.collect_pixels(create_pixels, set_pixel)
}
pub fn rgb_channels<R, G, B, Create, Set, Pixels>(
self,
create_pixels: Create,
set_pixel: Set,
) -> CollectPixels<
ReadRequiredChannel<ReadRequiredChannel<ReadRequiredChannel<NoneMore, R>, G>, B>,
(R, G, B),
Pixels,
Create,
Set,
>
where
R: FromNativeSample,
G: FromNativeSample,
B: FromNativeSample,
Create: Fn(Vec2<usize>, &RgbChannels) -> Pixels,
Set: Fn(&mut Pixels, Vec2<usize>, (R, G, B)),
{
self.specific_channels()
.required("R")
.required("G")
.required("B")
.collect_pixels(create_pixels, set_pixel)
}
pub fn specific_channels(self) -> ReadZeroChannels {
ReadZeroChannels {}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ReadAllLevels<DeepOrFlatSamples> {
pub read_samples: DeepOrFlatSamples,
}
impl<ReadDeepOrFlatSamples> ReadAllLevels<ReadDeepOrFlatSamples> {
pub fn all_channels(self) -> ReadAnyChannels<Self> {
ReadAnyChannels {
read_samples: self,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct AllLevelsReader<SamplesReader> {
levels: Levels<SamplesReader>,
}
pub trait ReadSamplesLevel {
type Reader: SamplesReader;
fn create_samples_level_reader(
&self,
header: &Header,
channel: &ChannelDescription,
level: Vec2<usize>,
resolution: Vec2<usize>,
) -> Result<Self::Reader>;
}
impl<S: ReadSamplesLevel> ReadSamples for ReadAllLevels<S> {
type Reader = AllLevelsReader<S::Reader>;
fn create_sample_reader(
&self,
header: &Header,
channel: &ChannelDescription,
) -> Result<Self::Reader> {
let data_size = header.layer_size / channel.sampling;
let levels = {
if let crate::meta::BlockDescription::Tiles(tiles) = &header.blocks {
match tiles.level_mode {
LevelMode::Singular => {
Levels::Singular(self.read_samples.create_samples_level_reader(
header,
channel,
Vec2(0, 0),
header.layer_size,
)?)
}
LevelMode::MipMap => Levels::Mip {
rounding_mode: tiles.rounding_mode,
level_data: {
let round = tiles.rounding_mode;
let maps: Result<LevelMaps<S::Reader>> =
mip_map_levels(round, data_size)
.map(|(index, level_size)| {
self.read_samples.create_samples_level_reader(
header,
channel,
Vec2(index, index),
level_size,
)
})
.collect();
maps?
},
},
LevelMode::RipMap => Levels::Rip {
rounding_mode: tiles.rounding_mode,
level_data: {
let round = tiles.rounding_mode;
let level_count_x = compute_level_count(round, data_size.width());
let level_count_y = compute_level_count(round, data_size.height());
let maps: Result<LevelMaps<S::Reader>> =
rip_map_levels(round, data_size)
.map(|(index, level_size)| {
self.read_samples.create_samples_level_reader(
header, channel, index, level_size,
)
})
.collect();
RipMaps {
map_data: maps?,
level_count: Vec2(level_count_x, level_count_y),
}
},
},
}
}
else {
Levels::Singular(self.read_samples.create_samples_level_reader(
header,
channel,
Vec2(0, 0),
data_size,
)?)
}
};
Ok(AllLevelsReader {
levels,
})
}
}
impl<S: SamplesReader> SamplesReader for AllLevelsReader<S> {
type Samples = Levels<S::Samples>;
fn filter_block(&self, _: TileCoordinates) -> bool {
true
}
fn read_line(&mut self, line: LineRef<'_>) -> UnitResult {
self.levels.get_level_mut(line.location.level)?.read_line(line)
}
fn into_samples(self) -> Self::Samples {
match self.levels {
Levels::Singular(level) => Levels::Singular(level.into_samples()),
Levels::Mip {
rounding_mode,
level_data,
} => Levels::Mip {
rounding_mode,
level_data: level_data.into_iter().map(|s| s.into_samples()).collect(),
},
Levels::Rip {
rounding_mode,
level_data,
} => Levels::Rip {
rounding_mode,
level_data: RipMaps {
level_count: level_data.level_count,
map_data: level_data.map_data.into_iter().map(|s| s.into_samples()).collect(),
},
},
}
}
}