use crate::consts::COLOR_CHANNEL_NUM_BLOCK_TYPES;
use super::block_based_image::BlockBasedImage;
pub struct RowSpec {
pub luma_y: u32,
pub component: usize,
pub curr_y: u32,
pub mcu_row_index: u32,
pub last_row_to_complete_mcu: bool,
pub skip: bool,
pub done: bool,
}
impl RowSpec {
pub fn get_row_spec_from_index(
decode_index: u32,
image_data: &[BlockBasedImage],
mcuv: u32, max_coded_heights: &[u32],
) -> RowSpec {
assert!(
image_data.len() <= COLOR_CHANNEL_NUM_BLOCK_TYPES,
"image_data should match components count"
);
let num_cmp = image_data.len();
let mut heights: Vec<u32> = Vec::with_capacity(num_cmp);
let mut component_multiple: Vec<u32> = Vec::with_capacity(num_cmp);
let mut mcu_multiple = 0;
for i in 0..num_cmp {
heights.push(image_data[i].get_original_height());
component_multiple.push(heights[i] / mcuv);
mcu_multiple += component_multiple[i];
}
let mcu_row = decode_index / mcu_multiple;
let min_row_luma_y = mcu_row * component_multiple[0];
let mut retval = RowSpec {
skip: false,
done: false,
mcu_row_index: mcu_row,
component: num_cmp,
luma_y: min_row_luma_y,
curr_y: 0,
last_row_to_complete_mcu: false,
};
let mut place_within_scan = decode_index - (mcu_row * mcu_multiple);
let mut i = num_cmp - 1;
loop {
if place_within_scan < component_multiple[i] {
retval.component = i;
retval.curr_y = (mcu_row * component_multiple[i]) + place_within_scan;
retval.last_row_to_complete_mcu =
(place_within_scan + 1 == component_multiple[i]) && (i == 0);
if retval.curr_y >= max_coded_heights[i] {
retval.skip = true;
retval.done = true; for j in 0..num_cmp - 1 {
if mcu_row * component_multiple[j] < max_coded_heights[j] {
retval.done = false;
}
}
}
if i == 0 {
retval.luma_y = retval.curr_y;
}
break;
} else {
place_within_scan -= component_multiple[i];
}
if i == 0 {
retval.skip = true;
retval.done = true;
break;
}
i -= 1;
}
return retval;
}
}