use alloc::vec;
use alloc::vec::Vec;
use super::tile::{ComponentTile, ResolutionTile, Tile};
use crate::error::{DecodingError, Result};
use alloc::boxed::Box;
use core::cmp::Ordering;
use core::iter;
#[derive(Default, Copy, Clone, Debug, PartialEq, Hash, Eq)]
pub(crate) struct ProgressionData {
pub(crate) layer_num: u8,
pub(crate) resolution: u8,
pub(crate) component: u8,
pub(crate) precinct: u64,
}
pub(crate) struct IteratorInput<'a> {
layers: (u8, u8),
tile: &'a Tile<'a>,
resolutions: (u8, u8),
components: (u8, u8),
}
impl<'a> IteratorInput<'a> {
pub(crate) fn new(tile: &'a Tile<'a>) -> Self {
Self::new_with_custom_bounds(
tile,
(0, u8::MAX),
(0, u8::MAX),
(0, u8::MAX),
)
}
pub(crate) fn new_with_custom_bounds(
tile: &'a Tile<'a>,
resolutions: (u8, u8),
layers: (u8, u8),
components: (u8, u8),
) -> Self {
Self::try_new_with_custom_bounds(tile, resolutions, layers, components)
.expect("valid progression iterator bounds")
}
pub(crate) fn try_new_with_custom_bounds(
tile: &'a Tile<'a>,
mut resolutions: (u8, u8),
mut layers: (u8, u8),
mut components: (u8, u8),
) -> Option<Self> {
let max_resolution = tile
.component_infos
.iter()
.map(|c| c.coding_style.parameters.num_resolution_levels)
.max()
.unwrap_or(0);
let max_layer = tile.num_layers;
let max_component = tile.component_infos.len() as u8;
resolutions.1 = resolutions.1.min(max_resolution);
layers.1 = layers.1.min(max_layer);
components.1 = components.1.min(max_component);
if resolutions.1 <= resolutions.0 || layers.1 <= layers.0 || components.1 <= components.0 {
return None;
}
Some(Self {
layers,
tile,
resolutions,
components,
})
}
fn min_layer(&self) -> u8 {
self.layers.0
}
fn max_layer(&self) -> u8 {
self.layers.1
}
fn min_resolution(&self) -> u8 {
self.resolutions.0
}
fn total_max_resolution(&self) -> u8 {
self.resolutions.1
}
fn max_resolution(&self, component_idx: u8) -> u8 {
self.total_max_resolution()
.min(self.tile.component_infos[component_idx as usize].num_resolution_levels())
}
fn min_comp(&self) -> u8 {
self.components.0
}
fn max_comp(&self) -> u8 {
self.components.1
}
fn component_tiles(&self) -> Vec<ComponentTile<'a>> {
self.tile
.component_infos
.iter()
.map(|c| ComponentTile::new(self.tile, c))
.collect::<Vec<_>>()
}
}
pub(crate) fn progression_iterator<'a>(
tile: &'a Tile<'a>,
) -> Result<Box<dyn Iterator<Item = ProgressionData> + 'a>> {
if tile.progression_changes.is_empty() {
return progression_iterator_for_order(tile.progression_order, IteratorInput::new(tile));
}
let mut iterators = Vec::with_capacity(tile.progression_changes.len());
for change in &tile.progression_changes {
let iter_input = IteratorInput::try_new_with_custom_bounds(
tile,
(change.resolution_start, change.resolution_end),
(0, change.layer_end),
(change.component_start, change.component_end),
)
.ok_or(DecodingError::InvalidProgressionIterator)?;
iterators.push(progression_iterator_for_order(
change.progression_order,
iter_input,
)?);
}
Ok(Box::new(iterators.into_iter().flatten()))
}
fn progression_iterator_for_order<'a>(
progression_order: super::codestream::ProgressionOrder,
iter_input: IteratorInput<'a>,
) -> Result<Box<dyn Iterator<Item = ProgressionData> + 'a>> {
let iterator: Box<dyn Iterator<Item = ProgressionData>> = match progression_order {
super::codestream::ProgressionOrder::LayerResolutionComponentPosition => {
Box::new(layer_resolution_component_position_progression(iter_input))
}
super::codestream::ProgressionOrder::ResolutionLayerComponentPosition => {
Box::new(resolution_layer_component_position_progression(iter_input))
}
super::codestream::ProgressionOrder::ResolutionPositionComponentLayer => Box::new(
resolution_position_component_layer_progression(iter_input)
.ok_or(DecodingError::InvalidProgressionIterator)?,
),
super::codestream::ProgressionOrder::PositionComponentResolutionLayer => Box::new(
position_component_resolution_layer_progression(iter_input)
.ok_or(DecodingError::InvalidProgressionIterator)?,
),
super::codestream::ProgressionOrder::ComponentPositionResolutionLayer => Box::new(
component_position_resolution_layer_progression(iter_input)
.ok_or(DecodingError::InvalidProgressionIterator)?,
),
};
Ok(iterator)
}
pub(crate) fn layer_resolution_component_position_progression<'a>(
input: IteratorInput<'a>,
) -> impl Iterator<Item = ProgressionData> + 'a {
let component_tiles = input.component_tiles();
let mut layer = input.min_layer();
let mut resolution = input.min_resolution();
let mut component_idx = input.min_comp();
let mut resolution_tile = ResolutionTile::new(component_tiles[0], resolution);
let mut precinct = 0;
iter::from_fn(move || {
if layer == input.max_layer() || resolution == input.total_max_resolution() {
return None;
}
if precinct == resolution_tile.num_precincts() {
loop {
precinct = 0;
component_idx += 1;
if component_idx == input.max_comp() {
component_idx = input.min_comp();
resolution += 1;
if resolution == input.max_resolution(component_idx) {
resolution = input.min_resolution();
layer += 1;
if layer == input.max_layer() {
return None;
}
}
}
resolution_tile =
ResolutionTile::new(component_tiles[component_idx as usize], resolution);
if resolution_tile.num_precincts() != 0 {
break;
}
}
}
let data = ProgressionData {
layer_num: layer,
resolution,
component: component_idx,
precinct,
};
precinct += 1;
Some(data)
})
}
pub(crate) fn resolution_layer_component_position_progression<'a>(
input: IteratorInput<'a>,
) -> impl Iterator<Item = ProgressionData> + 'a {
let component_tiles = input.component_tiles();
let mut layer = input.min_layer();
let mut resolution = input.min_resolution();
let mut component_idx = input.min_comp();
let mut resolution_tile =
ResolutionTile::new(component_tiles[component_idx as usize], resolution);
let mut precinct = 0;
iter::from_fn(move || {
if layer == input.max_layer() || resolution == input.total_max_resolution() {
return None;
}
if precinct == resolution_tile.num_precincts() {
loop {
precinct = 0;
component_idx += 1;
if component_idx == input.max_comp() {
component_idx = input.min_comp();
layer += 1;
if layer == input.max_layer() {
layer = input.min_layer();
resolution += 1;
if resolution == input.total_max_resolution() {
return None;
}
}
}
if resolution >= input.max_resolution(component_idx) {
continue;
}
resolution_tile =
ResolutionTile::new(component_tiles[component_idx as usize], resolution);
if resolution_tile.num_precincts() != 0 {
break;
}
}
}
let data = ProgressionData {
layer_num: layer,
resolution,
component: component_idx,
precinct,
};
precinct += 1;
Some(data)
})
}
struct PrecinctStore {
resolution: u8,
precinct_y: u32,
precinct_x: u32,
component_idx: u8,
precinct_idx: u64,
}
fn position_progression_common<'a>(
input: IteratorInput<'a>,
sort: impl FnMut(&PrecinctStore, &PrecinctStore) -> Ordering,
) -> Option<impl Iterator<Item = ProgressionData> + 'a> {
let mut elements = vec![];
for (component_idx, component) in input
.tile
.component_tiles()
.enumerate()
.skip(input.min_comp() as usize)
.take(input.max_comp() as usize - input.min_comp() as usize)
{
for (resolution, resolution_tile) in component
.resolution_tiles()
.enumerate()
.skip(input.min_resolution() as usize)
.take(input.total_max_resolution() as usize - input.min_resolution() as usize)
{
elements.extend(resolution_tile.precincts()?.map(|d| PrecinctStore {
precinct_y: d.r_y,
precinct_x: d.r_x,
component_idx: component_idx as u8,
resolution: resolution as u8,
precinct_idx: d.idx,
}));
}
}
elements.sort_by(sort);
Some(elements.into_iter().flat_map(move |e| {
(input.min_layer()..input.max_layer()).map(move |layer| ProgressionData {
layer_num: layer,
resolution: e.resolution,
component: e.component_idx,
precinct: e.precinct_idx,
})
}))
}
pub(crate) fn resolution_position_component_layer_progression<'a>(
input: IteratorInput<'a>,
) -> Option<impl Iterator<Item = ProgressionData> + 'a> {
position_progression_common(input, |p, s| {
p.resolution
.cmp(&s.resolution)
.then_with(|| p.precinct_y.cmp(&s.precinct_y))
.then_with(|| p.precinct_x.cmp(&s.precinct_x))
.then_with(|| p.component_idx.cmp(&s.component_idx))
.then_with(|| p.precinct_idx.cmp(&s.precinct_idx))
})
}
pub(crate) fn position_component_resolution_layer_progression<'a>(
input: IteratorInput<'a>,
) -> Option<impl Iterator<Item = ProgressionData> + 'a> {
position_progression_common(input, |p, s| {
p.precinct_y
.cmp(&s.precinct_y)
.then_with(|| p.precinct_x.cmp(&s.precinct_x))
.then_with(|| p.component_idx.cmp(&s.component_idx))
.then_with(|| p.resolution.cmp(&s.resolution))
.then_with(|| p.precinct_idx.cmp(&s.precinct_idx))
})
}
pub(crate) fn component_position_resolution_layer_progression<'a>(
input: IteratorInput<'a>,
) -> Option<impl Iterator<Item = ProgressionData> + 'a> {
position_progression_common(input, |p, s| {
p.component_idx
.cmp(&s.component_idx)
.then_with(|| p.precinct_y.cmp(&s.precinct_y))
.then_with(|| p.precinct_x.cmp(&s.precinct_x))
.then_with(|| p.resolution.cmp(&s.resolution))
.then_with(|| p.precinct_idx.cmp(&s.precinct_idx))
})
}