use rustdct::algorithm::type2and3_butterflies::{Type2And3Butterfly4, Type2And3Butterfly8};
#[cfg(test)]
#[rustfmt::skip]
mod tests {
use super::*;
#[test]
fn test_dct_8x8() {
let b = &mut [
[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 1., 1., 1., 1.],
[0., 0., 0., 0., 1., 1., 1., 1.],
[0., 0., 0., 0., 1., 1., 1., 1.],
[0., 0., 0., 0., 1., 1., 1., 1.],
];
dct_8x8(b);
assert_eq!(b, &[
[32., 0., 0., 0., 0., 0., 0., 0. ],
[ 0., 13.137071, 0.,-4.613126, 0., 3.0823913, 0.,-2.613126 ],
[ 0., 0., 0., 0., 0., 0., 0., 0. ],
[ 0.,-4.6131253, 0., 1.6199145, 0.,-1.0823917, 0., 0.91760784],
[ 0., 0., 0., 0., 0., 0., 0., 0. ],
[ 0., 3.082391, 0.,-1.0823922, 0., 0.7232312, 0.,-0.61312586],
[ 0., 0., 0., 0., 0., 0., 0., 0. ],
[ 0.,-2.6131256, 0., 0.9176079, 0.,-0.61312574, 0., 0.5197831 ],
]);
}
#[test]
fn test_idct_8x8() {
let b = &mut [
[32., 0., 0., 0., 0., 0., 0., 0. ],
[ 0., 13.137071, 0.,-4.613126, 0., 3.0823913, 0.,-2.613126 ],
[ 0., 0., 0., 0., 0., 0., 0., 0. ],
[ 0.,-4.6131253, 0., 1.6199145, 0.,-1.0823917, 0., 0.91760784],
[ 0., 0., 0., 0., 0., 0., 0., 0. ],
[ 0., 3.082391, 0.,-1.0823922, 0., 0.7232312, 0.,-0.61312586],
[ 0., 0., 0., 0., 0., 0., 0., 0. ],
[ 0.,-2.6131256, 0., 0.9176079, 0.,-0.61312574, 0., 0.5197831 ],
];
idct_8x8(b);
assert_eq!(b, &[
[1., 1., 1., 0.99999994, 0.000000059604645, 0., 0., 0. ],
[1., 1., 1., 0.99999994, 0.000000059604645, 0., -0.000000059604645, 0. ],
[0.99999994, 1., 1., 0.9999999, 0.00000008940697, 0.000000029802322,-0.000000059604645, 0.000000059604645],
[0.9999999, 0.99999994, 0.99999994, 0.99999994, 0.000000059604645, 0.000000059604645, 0.000000059604645, 0.00000014901161 ],
[0.00000014901161, 0.000000059604645, 0.000000059604645, 0.000000059604645, 0.99999994, 0.99999994, 0.99999994, 0.9999999 ],
[0.000000059604645,-0.000000059604645, 0.000000029802322, 0.00000008940697, 0.9999999, 1., 1., 0.99999994 ],
[0., -0.000000059604645, 0., 0.000000059604645, 0.99999994, 1., 1., 1. ],
[0., 0., 0., 0.000000059604645, 0.99999994, 1., 1., 1. ],
]);
}
#[test]
fn test_idct_8x8_distort() {
let b = &mut [
[32., 0., 0., 0., 0., 0., 0., 0.],
[ 0.,13.137071, 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
];
idct_8x8(b);
assert_eq!(b, &[
[ 1.2898169, 1.1695745, 0.9473953, 0.6571044, 0.34289566, 0.052604675,-0.16957444,-0.28981692 ],
[ 1.1695745, 1.0676378, 0.8792834, 0.63318664, 0.36681336, 0.12071654, -0.0676378, -0.16957444 ],
[ 0.9473953, 0.8792834, 0.7534291, 0.5889925, 0.41100752, 0.24657089, 0.12071654, 0.052604645],
[ 0.6571044, 0.63318664, 0.5889925, 0.53125, 0.46875, 0.41100752, 0.36681336, 0.34289563 ],
[ 0.34289563, 0.36681336, 0.41100752, 0.46875, 0.53125, 0.5889925, 0.63318664, 0.6571044 ],
[ 0.052604645, 0.12071654, 0.24657089, 0.41100752, 0.5889925, 0.7534291, 0.8792834, 0.9473953 ],
[-0.16957444, -0.0676378, 0.12071654, 0.36681336, 0.63318664, 0.8792834, 1.0676378, 1.1695745 ],
[-0.28981692, -0.16957444, 0.052604675, 0.34289566, 0.6571044, 0.9473953, 1.1695745, 1.2898169 ],
]);
}
#[test]
fn test_dct_4x8() {
let b = &mut [
[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0.],
];
dct_4x8(b);
assert_eq!(b, &[
[16.0, 0., 0., 0., 0., 0., 0., 0.],
[10.251661, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[-3.599905, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 2.4053788, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[-2.0391824, 0., 0., 0., 0., 0., 0., 0.],
]);
}
#[test]
fn test_idct_4x8() {
let b = &mut [
[16.0, 0., 0., 0., 0., 0., 0., 0.],
[10.251661, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[-3.599905, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 2.4053788, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[-2.0391824, 0., 0., 0., 0., 0., 0., 0.],
];
idct_4x8(b);
assert_eq!(b, &[
[ 1.438622, 1.3291135, 1.0172594, 0.5505368, 0., 0., 0., 0.],
[ 1.5111153, 1.3960885, 1.0685198, 0.5782788, 0., 0., 0., 0.],
[ 1.2016646, 1.1101933, 0.8497052, 0.45985717, 0., 0., 0., 0.],
[ 1.084887, 1.0023048, 0.767131, 0.41516823, 0., 0., 0., 0.],
[-0.10147545, -0.09375111, -0.07175396, -0.038832966, 0., 0., 0., 0.],
[-0.21844524, -0.20181715, -0.15446416, -0.08359535, 0., 0., 0., 0.],
[-0.0330514, -0.03053552, -0.023370862,-0.01264821, 0., 0., 0., 0.],
[-0.040344596,-0.037273556,-0.028527945,-0.015439197, 0., 0., 0., 0.],
]);
}
#[test]
fn test_idct_4x8_distort() {
let b = &mut [
[16.0, 0., 0., 0., 0., 0., 0., 0.],
[10.251661, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[-3.599905, 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
];
idct_4x8(b);
assert_eq!(b, &[
[1.4157348, 1.3079684, 1.0010756, 0.5417782, 0.0, 0.0, 0.0, 0.0],
[1.4696376, 1.357768, 1.0391908, 0.56240594, 0.0, 0.0, 0.0, 0.0],
[1.3769432, 1.2721297, 0.97364587, 0.5269334, 0.0, 0.0, 0.0, 0.0],
[0.83146954, 0.7681776, 0.5879378, 0.31818965, 0.0, 0.0, 0.0, 0.0],
[0.09494825, 0.08772074, 0.06713856, 0.036335126, 0.0, 0.0, 0.0, 0.0],
[-0.25992286,-0.24013743, -0.18379325, -0.09946818, 0.0, 0.0, 0.0, 0.0],
[-0.12317133,-0.11379549, -0.08709529, -0.047135606, 0.0, 0.0, 0.0, 0.0],
[0.059791297, 0.055239946, 0.042278826, 0.02288115, 0.0, 0.0, 0.0, 0.0],
]);
}
#[test]
fn test_swapaxes() {
let mut b = &mut [
[1, 1, 1, 0, 0, 1, 1, 1],
[1, 0, 1, 0, 3, 1, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 4, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
[1, 2, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
];
swapaxes_8x8(&mut b);
assert_eq!(b, &[
[1, 1, 1, 0, 0, 1, 1, 1],
[1, 0, 1, 0, 0, 1, 2, 1],
[1, 1, 1, 0, 0, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 3, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 4, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
]);
}
}
pub fn dct_8x8(b: &mut [[f32; 8]; 8]) {
let algo = Type2And3Butterfly8::<f32>::new();
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct2(v));
swapaxes_8x8(b);
}
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct2(v));
swapaxes_8x8(b);
}
}
#[allow(dead_code)]
pub fn idct_8x8(b: &mut [[f32; 8]; 8]) {
let algo = Type2And3Butterfly8::<f32>::new();
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct3(v));
swapaxes_8x8(b);
}
b.iter_mut().flatten().for_each(|n| *n /= 4.);
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct3(v));
swapaxes_8x8(b);
}
b.iter_mut().flatten().for_each(|n| *n /= 4.);
}
pub fn dct_4x8(b: &mut [[f32; 8]; 8]) {
let algo = Type2And3Butterfly4::<f32>::new();
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct2(v));
swapaxes_8x8(b);
}
let algo = Type2And3Butterfly8::<f32>::new();
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct2(v));
swapaxes_8x8(b);
}
}
#[allow(dead_code)]
pub fn idct_4x8(b: &mut [[f32; 8]; 8]) {
let algo = Type2And3Butterfly4::<f32>::new();
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct2(v));
swapaxes_8x8(b);
}
b.iter_mut().flatten().for_each(|n| *n /= 4.);
let algo = Type2And3Butterfly8::<f32>::new();
unsafe {
b.iter_mut().for_each(|v| algo.process_inplace_dct2(v));
swapaxes_8x8(b);
}
b.iter_mut().flatten().for_each(|n| *n /= 4.);
}
fn swapaxes_8x8<T>(b: &mut [[T; 8]; 8]) {
for y in 1..8 {
for x in 0..y {
unsafe { std::ptr::swap(&mut b[y][x], &mut b[x][y]) };
}
}
}
pub fn dct_8x8_feature(b: &[[f32; 8]; 8]) -> [f32; 10] {
let mut b = b.clone();
dct_8x8(&mut b);
return extract(&b);
}
pub fn dct_4x8_feature(b: &[[f32; 8]; 8]) -> [f32; 10] {
let mut b = b.clone();
dct_4x8(&mut b);
return extract(&b);
}
#[rustfmt::skip]
pub fn extract(b: &[[f32; 8]; 8]) -> [f32; 10] {
return [b[0][0], b[1][0], b[0][1], b[0][2], b[1][1], b[2][0], b[3][0], b[2][1], b[1][2], b[0][3]];
}
#[rustfmt::skip]
pub fn similarity(f: &[f32; 10], f2: &[f32; 10]) -> f32 {
(f[0] - f2[0]).abs()
+ (f[1] - f2[1]).abs()
+ (f[2] - f2[2]).abs()
+ (f[3] - f2[3]).abs()
+ (f[4] - f2[4]).abs()
+ (f[5] - f2[5]).abs()
+ (f[6] - f2[6]).abs()
+ (f[7] - f2[7]).abs()
+ (f[8] - f2[8]).abs()
+ (f[9] - f2[9]).abs()
}