use std::cmp;
use super::component_info::ComponentInfo;
use super::jpeg_header::JpegHeader;
#[derive(Debug, Clone)]
struct TrucateComponentsInfo {
trunc_bcv: u32,
trunc_bc: u32,
}
#[derive(Debug, Clone)]
pub struct TruncateComponents {
trunc_info: Vec<TrucateComponentsInfo>,
pub components_count: usize,
pub mcu_count_horizontal: u32,
pub mcu_count_vertical: u32,
}
impl Default for TruncateComponents {
fn default() -> Self {
return TruncateComponents {
trunc_info: Vec::new(),
components_count: 0,
mcu_count_horizontal: 0,
mcu_count_vertical: 0,
};
}
}
impl TruncateComponents {
pub fn init(&mut self, jpeg_header: &JpegHeader) {
self.mcu_count_horizontal = jpeg_header.mcuh.get();
self.mcu_count_vertical = jpeg_header.mcuv.get();
self.components_count = jpeg_header.cmpc;
for i in 0..jpeg_header.cmpc {
self.trunc_info.push(TrucateComponentsInfo {
trunc_bcv: jpeg_header.cmp_info[i].bcv,
trunc_bc: jpeg_header.cmp_info[i].bc,
});
}
}
pub fn get_max_coded_heights(&self) -> Vec<u32> {
let mut retval = Vec::<u32>::new();
for i in 0..self.components_count {
retval.push(self.trunc_info[i].trunc_bcv);
}
return retval;
}
pub fn set_truncation_bounds(&mut self, jpeg_header: &JpegHeader, max_d_pos: [u32; 4]) {
for i in 0..self.components_count {
TruncateComponents::set_block_count_d_pos(
&mut self.trunc_info[i],
&jpeg_header.cmp_info[i],
max_d_pos[i] + 1,
self.mcu_count_vertical,
);
}
}
pub fn get_block_height(&self, cmp: usize) -> u32 {
return self.trunc_info[cmp].trunc_bcv;
}
fn set_block_count_d_pos(
ti: &mut TrucateComponentsInfo,
ci: &ComponentInfo,
trunc_bc: u32,
mcu_count_vertical: u32,
) {
assert!(
ci.bcv == (ci.bc / ci.bch) + (if ci.bc % ci.bch != 0 { 1 } else { 0 }),
"SetBlockCountDpos"
);
let mut vertical_scan_lines = cmp::min(
(trunc_bc / ci.bch) + (if trunc_bc % ci.bch != 0 { 1 } else { 0 }),
ci.bcv,
);
let ratio = TruncateComponents::get_min_vertical_extcmp_multiple(&ci, mcu_count_vertical);
while vertical_scan_lines % ratio != 0 && vertical_scan_lines + 1 <= ci.bcv {
vertical_scan_lines += 1;
}
assert!(
vertical_scan_lines <= ci.bcv,
"verticalScanLines <= ci.Info.bcv"
);
ti.trunc_bcv = vertical_scan_lines;
ti.trunc_bc = trunc_bc;
}
fn get_min_vertical_extcmp_multiple(cmp_info: &ComponentInfo, mcu_count_vertical: u32) -> u32 {
let luma_height = cmp_info.bcv;
return luma_height / mcu_count_vertical;
}
pub fn get_component_sizes_in_blocks(&self) -> Vec<u32> {
let mut retval = Vec::new();
for i in 0..self.components_count {
retval.push(self.trunc_info[i].trunc_bc);
}
return retval;
}
}