#[derive(Debug, Clone)]
pub struct QuantTable {
pub values: [u16; 64],
}
impl QuantTable {
pub fn new(values: [u16; 64]) -> Self {
Self { values }
}
}
#[derive(Debug, Clone)]
pub struct DctGrid {
blocks_wide: usize,
blocks_tall: usize,
coeffs: Vec<i16>,
}
impl DctGrid {
pub fn new(blocks_wide: usize, blocks_tall: usize) -> Self {
Self {
blocks_wide,
blocks_tall,
coeffs: vec![0i16; blocks_wide * blocks_tall * 64],
}
}
pub fn blocks_wide(&self) -> usize {
self.blocks_wide
}
pub fn blocks_tall(&self) -> usize {
self.blocks_tall
}
pub fn get(&self, br: usize, bc: usize, i: usize, j: usize) -> i16 {
self.coeffs[self.index(br, bc, i, j)]
}
pub fn set(&mut self, br: usize, bc: usize, i: usize, j: usize, val: i16) {
let idx = self.index(br, bc, i, j);
self.coeffs[idx] = val;
}
pub fn block_mut(&mut self, br: usize, bc: usize) -> &mut [i16] {
let start = (br * self.blocks_wide + bc) * 64;
&mut self.coeffs[start..start + 64]
}
pub fn block(&self, br: usize, bc: usize) -> &[i16] {
let start = (br * self.blocks_wide + bc) * 64;
&self.coeffs[start..start + 64]
}
pub fn total_blocks(&self) -> usize {
self.blocks_wide * self.blocks_tall
}
pub fn coeffs_mut(&mut self) -> &mut [i16] {
&mut self.coeffs
}
pub fn coeffs(&self) -> &[i16] {
&self.coeffs
}
fn index(&self, br: usize, bc: usize, i: usize, j: usize) -> usize {
debug_assert!(br < self.blocks_tall, "block row {br} >= {}", self.blocks_tall);
debug_assert!(bc < self.blocks_wide, "block col {bc} >= {}", self.blocks_wide);
debug_assert!(i < 8 && j < 8);
(br * self.blocks_wide + bc) * 64 + i * 8 + j
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn grid_get_set() {
let mut grid = DctGrid::new(2, 3);
assert_eq!(grid.blocks_wide(), 2);
assert_eq!(grid.blocks_tall(), 3);
assert_eq!(grid.total_blocks(), 6);
assert_eq!(grid.get(0, 0, 0, 0), 0);
assert_eq!(grid.get(2, 1, 7, 7), 0);
grid.set(1, 0, 3, 4, 42);
assert_eq!(grid.get(1, 0, 3, 4), 42);
assert_eq!(grid.get(1, 0, 3, 3), 0);
assert_eq!(grid.get(0, 0, 3, 4), 0);
}
#[test]
fn block_slice_access() {
let mut grid = DctGrid::new(1, 1);
grid.set(0, 0, 0, 0, 100); grid.set(0, 0, 7, 7, -50);
let blk = grid.block(0, 0);
assert_eq!(blk[0], 100);
assert_eq!(blk[63], -50);
assert_eq!(blk.len(), 64);
}
#[test]
fn block_mut_access() {
let mut grid = DctGrid::new(2, 2);
let blk = grid.block_mut(1, 1);
for (i, v) in blk.iter_mut().enumerate() {
*v = i as i16;
}
assert_eq!(grid.get(1, 1, 0, 0), 0);
assert_eq!(grid.get(1, 1, 0, 1), 1);
assert_eq!(grid.get(1, 1, 7, 7), 63);
assert_eq!(grid.get(0, 0, 0, 0), 0);
}
#[test]
fn quant_table() {
let mut vals = [0u16; 64];
vals[0] = 16;
vals[63] = 99;
let qt = QuantTable::new(vals);
assert_eq!(qt.values[0], 16);
assert_eq!(qt.values[63], 99);
}
}