pub const ZIGZAG_SCAN: [usize; 64] = [
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20,
13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59,
52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
];
#[must_use]
pub fn inverse_zigzag(coeffs: &[i32; 64]) -> [i32; 64] {
let mut raster = [0i32; 64];
for (scan_idx, &raster_idx) in ZIGZAG_SCAN.iter().enumerate() {
raster[raster_idx] = coeffs[scan_idx];
}
raster
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zigzag_scan_is_a_permutation() {
let mut seen = [false; 64];
for &raster in &ZIGZAG_SCAN {
assert!(raster < 64, "raster index {raster} out of range");
assert!(!seen[raster], "duplicate raster index {raster}");
seen[raster] = true;
}
assert!(seen.iter().all(|s| *s), "not all raster positions covered");
}
#[test]
fn dc_at_index_zero() {
assert_eq!(ZIGZAG_SCAN[0], 0);
}
#[test]
fn highest_frequency_at_end() {
assert_eq!(ZIGZAG_SCAN[63], 63);
}
#[test]
fn inverse_zigzag_round_trip() {
let raster: [i32; 64] = std::array::from_fn(|i| i as i32);
let mut scan_buf = [0i32; 64];
for (scan_idx, &raster_idx) in ZIGZAG_SCAN.iter().enumerate() {
scan_buf[scan_idx] = raster[raster_idx];
}
let recovered = inverse_zigzag(&scan_buf);
assert_eq!(recovered, raster);
}
}