use crate::buffer::Buffer;
use super::{ObuContext, ObuError, frame_header::TileInfo};
#[derive(Debug, Clone)]
pub struct TileGroupHeader {
pub tile_num: usize,
pub tile_row: usize,
pub tile_col: usize,
pub tile_size: usize,
pub data_offset: usize,
}
#[derive(Debug, Clone)]
pub struct TileGroup {
pub tg_start: usize,
pub tg_end: usize,
pub tiles: Vec<TileGroupHeader>,
}
impl TileGroup {
pub fn empty() -> Self {
Self {
tg_start: 0,
tg_end: 0,
tiles: Vec::new(),
}
}
pub fn decode(
ctx: &mut ObuContext,
buf: &mut Buffer,
tile_info: &TileInfo,
num_tiles: usize,
) -> Result<Self, ObuError> {
let mut tg_start = 0usize;
let mut tg_end = num_tiles - 1;
if num_tiles > 1 {
let tile_start_and_end_present = buf.get_bit();
if tile_start_and_end_present {
let tile_bits = tile_info.tile_cols_log2 + tile_info.tile_rows_log2;
tg_start = buf.get_bits(tile_bits) as usize;
tg_end = buf.get_bits(tile_bits) as usize;
}
}
buf.byte_align();
let mut tiles = Vec::with_capacity(tg_end - tg_start + 1);
for tile_num in tg_start..=tg_end {
let tile_row = tile_num / tile_info.tile_cols;
let tile_col = tile_num % tile_info.tile_cols;
let last_tile = tile_num == tg_end;
let (tile_size, data_offset) = if !last_tile {
let tile_size = buf.get_le(tile_info.tile_size_bytes) as usize + 1;
let offset = buf.bytes_consumed();
(tile_size, offset)
} else {
let offset = buf.bytes_consumed();
(0, offset)
};
tiles.push(TileGroupHeader {
tile_num,
tile_row,
tile_col,
tile_size,
data_offset,
});
if !last_tile && tile_size > 0 {
buf.seek_bits(tile_size * 8);
}
ctx.tile_num = tile_num;
}
if tg_end == num_tiles - 1 {
ctx.seen_frame_header = false;
}
Ok(Self {
tg_start,
tg_end,
tiles,
})
}
}