use std::ops::Range;
#[cfg(feature="ipp")]
mod dwt1d;
#[cfg(feature="ipp")]
mod dwt2d;
#[cfg(feature="ipp")]
pub use dwt1d::*;
#[cfg(feature="ipp")]
pub use dwt2d::*;
pub mod bank {
pub const HAAR_LOW : [f32; 2] = [1., 1.];
pub const HAAR_HIGH : [f32; 2] = [-1., 1.];
pub const HAAR_LOW_INV : [f32; 2] = [1., 1.];
pub const HAAR_LOW_HIGH : [f32; 2] = [1., -1.];
pub const DAUB4_LOW : [f32; 4] = [
0.48296291314453414337487159986,
0.83651630373780790557529378092,
0.22414386804201338102597276224,
-0.12940952255126038117444941881
];
pub const DAUB4_HIGH : [f32; 4] = [
-0.12940952255126038117444941881,
-0.22414386804201338102597276224,
0.83651630373780790557529378092,
-0.48296291314453414337487159986
];
pub fn derive_diff<const U : usize>(h_k : &[f32; U]) -> [f32; U] {
let mut h_kp1 = h_k.clone();
for t in 0..U {
let ix = ((U as i32 - 1 - t as i32) % U as i32) as usize;
h_kp1[t] = (-1. as f32).powf(t as f32) * h_k[ix];
}
h_kp1
}
}
#[test]
fn advance_level() {
use crate::dwt::bank::*;
println!("{:?} {:?}", derive_diff(&DAUBECHIES), DAUB4_HIGH);
}
#[derive(Clone, Copy, Debug)]
pub enum Basis {
Haar(bool),
Daubechies(usize, bool),
BSpline(usize, bool)
}
impl Basis {
fn len(&self) -> usize {
match self {
Basis::Daubechies(4, _) => 4,
_ => unimplemented!()
}
}
fn coefficients(&self) -> (&'static [f32; 4], &'static [f32; 4]) {
match self {
Basis::Daubechies(4, _) => (&bank::DAUB4_LOW, &bank::DAUB4_HIGH),
_ => panic!("Unimplemented basis {:?}", self)
}
}
}
pub fn is_valid_dwt_len(len : usize) -> bool {
len > 1 && (len as f64).log2().fract() == 0.0
}
pub fn is_valid_dwt_side(len : usize) -> bool {
is_valid_dwt_len(side_len(len))
}
pub fn dwt_max_levels(n : usize) -> usize {
(n as f32).log2() as usize - 1
}
fn dwt_level_index(n : usize, lvl : usize) -> Range<usize> {
let ix = n / (2usize).pow(lvl as u32 + 1);
ix..2*ix
}
fn verify_dwt_dimensions(src_len : usize, coarse_len : usize, detail_len : usize) {
assert!(src_len / 2 == coarse_len);
assert!(src_len / 2 == detail_len);
for len in [src_len, coarse_len, detail_len].iter() {
assert!(is_valid_dwt_len(*len));
}
}
fn verify_dwt1d_dimensions(src : &[f32], coarse : &[f32], detail : &[f32]) {
verify_dwt_dimensions(src.len(), coarse.len(), detail.len());
}
fn verify_dwt2d_dimensions(src : &[f32], coarse : &[f32], detail_x : &[f32], detail_y : &[f32], detail_xy : &[f32]) {
verify_dwt_dimensions(side_len(src.len()), side_len(coarse.len()), side_len(detail_x.len()));
verify_dwt_dimensions(side_len(src.len()), side_len(coarse.len()), side_len(detail_y.len()));
verify_dwt_dimensions(side_len(src.len()), side_len(coarse.len()), side_len(detail_xy.len()));
}
fn side_len(len : usize) -> usize {
let sq_len = (len as f32).sqrt();
assert!(sq_len.fract() == 0.0);
sq_len as usize
}
fn index_and_prev_mut<T>(levels : &mut [T], last : usize) -> (&mut T, &mut T) {
assert!(last >= 1 && last <= levels.len() - 1);
assert!(levels.len() >= 2);
let (curr, prev) = levels[last-1..last+1].split_last_mut().unwrap();
assert!(prev.len() == 1);
(&mut prev[0], curr)
}