use rustdct::{DCTplanner, TransformType2And3};
use transpose::transpose;
use std::sync::Arc;
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, mut packed_2d: Vec<f32>) -> Vec<f32> {
let Self { ref row_dct, ref col_dct, width, height } = *self;
let trunc_len = width * height;
assert_eq!(trunc_len * 2, packed_2d.len());
{
let (packed_2d, scratch) = packed_2d.split_at_mut(trunc_len);
for (row_in, row_out) in packed_2d.chunks_mut(width)
.zip(scratch.chunks_mut(width)) {
row_dct.process_dct2(row_in, row_out);
}
transpose(scratch, packed_2d, width, height);
for (row_in, row_out) in packed_2d.chunks_mut(height)
.zip(scratch.chunks_mut(height)) {
col_dct.process_dct2(row_in, row_out);
}
transpose(scratch, packed_2d, width, height);
}
packed_2d.truncate(trunc_len);
packed_2d
}
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() {
}