use crate::huffman::{
STD_AC_CHROMINANCE_BITS, STD_AC_CHROMINANCE_VALUES, STD_AC_LUMINANCE_BITS,
STD_AC_LUMINANCE_VALUES, STD_DC_CHROMINANCE_BITS, STD_DC_CHROMINANCE_VALUES,
STD_DC_LUMINANCE_BITS, STD_DC_LUMINANCE_VALUES,
};
#[derive(Clone, Debug)]
pub struct RateTable {
sizes: [u8; 256],
}
impl RateTable {
pub fn from_bits_values(bits: &[u8; 16], values: &[u8]) -> Self {
let mut sizes = [0u8; 256];
let mut val_idx = 0;
for (length_minus_1, &count) in bits.iter().enumerate() {
let length = (length_minus_1 + 1) as u8;
for _ in 0..count {
if val_idx < values.len() {
sizes[values[val_idx] as usize] = length;
val_idx += 1;
}
}
}
Self { sizes }
}
pub fn standard_luma_ac() -> Self {
Self::from_bits_values(&STD_AC_LUMINANCE_BITS, &STD_AC_LUMINANCE_VALUES)
}
pub fn standard_chroma_ac() -> Self {
Self::from_bits_values(&STD_AC_CHROMINANCE_BITS, &STD_AC_CHROMINANCE_VALUES)
}
pub fn standard_luma_dc() -> Self {
Self::from_bits_values(&STD_DC_LUMINANCE_BITS, &STD_DC_LUMINANCE_VALUES)
}
pub fn standard_chroma_dc() -> Self {
Self::from_bits_values(&STD_DC_CHROMINANCE_BITS, &STD_DC_CHROMINANCE_VALUES)
}
#[inline]
pub fn get_code_length(&self, symbol: u8) -> u8 {
self.sizes[symbol as usize]
}
#[inline]
pub fn get_code(&self, symbol: u8) -> (u32, u8) {
(0, self.sizes[symbol as usize])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_standard_luma_ac_has_eob() {
let table = RateTable::standard_luma_ac();
assert!(table.get_code_length(0x00) > 0);
assert!(table.get_code_length(0xF0) > 0);
}
#[test]
fn test_standard_chroma_ac_has_eob() {
let table = RateTable::standard_chroma_ac();
assert!(table.get_code_length(0x00) > 0);
assert!(table.get_code_length(0xF0) > 0);
}
#[test]
fn test_standard_dc_tables() {
let luma = RateTable::standard_luma_dc();
let chroma = RateTable::standard_chroma_dc();
assert!(luma.get_code_length(0) > 0);
assert!(chroma.get_code_length(0) > 0);
assert!(luma.get_code_length(8) > 0);
assert!(chroma.get_code_length(8) > 0);
}
#[test]
fn test_get_code_compat() {
let table = RateTable::standard_luma_ac();
let (code, size) = table.get_code(0x00);
assert_eq!(code, 0); assert!(size > 0);
}
#[test]
fn test_unassigned_symbol_returns_zero() {
let table = RateTable::standard_luma_ac();
let size = table.get_code_length(0xFF);
let _ = size;
}
}