use std::sync::Arc;
use rustdct::{DctPlanner, TransformType2And3};
pub const SIZE_MULTIPLIER: u32 = 2;
pub const SIZE_MULTIPLIER_U: usize = SIZE_MULTIPLIER as usize;
pub struct DctCtxt {
row_dct: Arc<dyn TransformType2And3<f32>>,
col_dct: Arc<dyn TransformType2And3<f32>>,
width: usize,
height: usize,
}
impl DctCtxt {
pub fn new(width: u32, height: u32) -> Self {
let mut planner = DctPlanner::new();
let width = width as usize * SIZE_MULTIPLIER_U;
let height = height as usize * SIZE_MULTIPLIER_U;
DctCtxt {
row_dct: planner.plan_dct2(width),
col_dct: planner.plan_dct2(height),
width,
height,
}
}
pub fn width(&self) -> u32 {
self.width as u32
}
pub fn height(&self) -> u32 {
self.height as u32
}
pub fn dct_2d(&self, packed_2d: &mut [f32]) {
let Self {
ref row_dct,
ref col_dct,
width,
height,
} = *self;
packed_2d
.chunks_mut(width)
.for_each(|buffer| row_dct.process_dct2(buffer));
packed_2d
.chunks_mut(height)
.for_each(|buffer| col_dct.process_dct2(buffer));
}
pub fn crop_2d(&self, packed: Vec<f32>) -> Vec<f32> {
crop_2d_dct(packed, self.width)
}
}
fn crop_2d_dct<T: Copy>(mut packed: Vec<T>, rowstride: usize) -> Vec<T> {
assert_eq!(rowstride % SIZE_MULTIPLIER_U, 0);
assert!(
rowstride / SIZE_MULTIPLIER_U > 0,
"rowstride cannot be cropped: {}",
rowstride
);
let new_rowstride = rowstride / SIZE_MULTIPLIER_U;
for new_row in 0..packed.len() / (rowstride * SIZE_MULTIPLIER_U) {
let (dest, src) = packed.split_at_mut(new_row * new_rowstride + rowstride);
let dest_start = dest.len() - new_rowstride;
let src_start = new_rowstride * new_row;
let src_end = src_start + new_rowstride;
dest[dest_start..].copy_from_slice(&src[src_start..src_end]);
}
let new_len = packed.len() / (SIZE_MULTIPLIER_U * SIZE_MULTIPLIER_U);
packed.truncate(new_len);
packed
}
#[test]
fn test_crop_2d_dct() {
let packed: Vec<i32> = (0..64).collect();
assert_eq!(
crop_2d_dct(packed.clone(), 8),
[
0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, ]
);
}
#[test]
fn test_transpose() {}