use crate::types::ProgOrder;
#[derive(Debug, Clone)]
pub struct PiImage {
pub num_comps: u32,
pub num_res: Vec<u32>,
pub num_precincts: Vec<Vec<(u32, u32)>>,
}
#[derive(Debug, Clone)]
pub struct PiParams {
pub num_layers: u32,
pub prog_order: ProgOrder,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PacketIndex {
pub layer: u32,
pub res: u32,
pub comp: u32,
pub precinct: u32,
}
pub struct PiIterator {
#[allow(dead_code)]
image: PiImage,
#[allow(dead_code)]
params: PiParams,
packets: Vec<PacketIndex>,
pos: usize,
}
impl PiIterator {
pub fn new(image: PiImage, params: PiParams) -> Self {
let packets = match params.prog_order {
ProgOrder::Lrcp => generate_lrcp(&image, ¶ms),
ProgOrder::Rlcp => generate_rlcp(&image, ¶ms),
ProgOrder::Rpcl => generate_rpcl(&image, ¶ms),
ProgOrder::Pcrl => generate_pcrl(&image, ¶ms),
ProgOrder::Cprl => generate_cprl(&image, ¶ms),
};
Self {
image,
params,
packets,
pos: 0,
}
}
pub fn packet_count(&self) -> usize {
self.packets.len()
}
pub fn packets(&self) -> &[PacketIndex] {
&self.packets
}
}
impl Iterator for PiIterator {
type Item = PacketIndex;
fn next(&mut self) -> Option<PacketIndex> {
if self.pos < self.packets.len() {
let pkt = self.packets[self.pos];
self.pos += 1;
Some(pkt)
} else {
None
}
}
}
fn total_precincts(image: &PiImage, comp: u32, res: u32) -> u32 {
let (pw, ph) = image.num_precincts[comp as usize][res as usize];
pw * ph
}
fn max_res(image: &PiImage) -> u32 {
image.num_res.iter().copied().max().unwrap_or(0)
}
fn max_precincts_at_res(image: &PiImage, res: u32) -> u32 {
let mut max_p = 0u32;
for comp in 0..image.num_comps {
if res < image.num_res[comp as usize] {
max_p = max_p.max(total_precincts(image, comp, res));
}
}
max_p
}
fn global_max_precincts(image: &PiImage) -> u32 {
let mut max_p = 0u32;
for comp in 0..image.num_comps {
for res in 0..image.num_res[comp as usize] {
max_p = max_p.max(total_precincts(image, comp, res));
}
}
max_p
}
fn generate_lrcp(image: &PiImage, params: &PiParams) -> Vec<PacketIndex> {
let mut packets = Vec::new();
let max_r = max_res(image);
for layer in 0..params.num_layers {
for res in 0..max_r {
for comp in 0..image.num_comps {
if res >= image.num_res[comp as usize] {
continue;
}
let num_p = total_precincts(image, comp, res);
for precinct in 0..num_p {
packets.push(PacketIndex {
layer,
res,
comp,
precinct,
});
}
}
}
}
packets
}
fn generate_rlcp(image: &PiImage, params: &PiParams) -> Vec<PacketIndex> {
let mut packets = Vec::new();
let max_r = max_res(image);
for res in 0..max_r {
for layer in 0..params.num_layers {
for comp in 0..image.num_comps {
if res >= image.num_res[comp as usize] {
continue;
}
let num_p = total_precincts(image, comp, res);
for precinct in 0..num_p {
packets.push(PacketIndex {
layer,
res,
comp,
precinct,
});
}
}
}
}
packets
}
fn generate_rpcl(image: &PiImage, params: &PiParams) -> Vec<PacketIndex> {
let mut packets = Vec::new();
let max_r = max_res(image);
for res in 0..max_r {
let max_p = max_precincts_at_res(image, res);
for precinct in 0..max_p {
for comp in 0..image.num_comps {
if res >= image.num_res[comp as usize] {
continue;
}
if precinct >= total_precincts(image, comp, res) {
continue;
}
for layer in 0..params.num_layers {
packets.push(PacketIndex {
layer,
res,
comp,
precinct,
});
}
}
}
}
packets
}
fn generate_pcrl(image: &PiImage, params: &PiParams) -> Vec<PacketIndex> {
let mut packets = Vec::new();
let max_p = global_max_precincts(image);
for precinct in 0..max_p {
for comp in 0..image.num_comps {
let max_r = image.num_res[comp as usize];
for res in 0..max_r {
if precinct >= total_precincts(image, comp, res) {
continue;
}
for layer in 0..params.num_layers {
packets.push(PacketIndex {
layer,
res,
comp,
precinct,
});
}
}
}
}
packets
}
fn generate_cprl(image: &PiImage, params: &PiParams) -> Vec<PacketIndex> {
let mut packets = Vec::new();
for comp in 0..image.num_comps {
let max_r = image.num_res[comp as usize];
let mut max_p = 0u32;
for res in 0..max_r {
max_p = max_p.max(total_precincts(image, comp, res));
}
for precinct in 0..max_p {
for res in 0..max_r {
if precinct >= total_precincts(image, comp, res) {
continue;
}
for layer in 0..params.num_layers {
packets.push(PacketIndex {
layer,
res,
comp,
precinct,
});
}
}
}
}
packets
}