use crate::foreign::ipp::ippi::*;
use crate::foreign::ipp::ippcore::{self, ippMalloc};
use crate::dwt::dwt1d;
use crate::ipputils::check_status;
use crate::ipputils::{self, row_size_bytes};
use nalgebra::DMatrix;
use crate::dwt::*;
pub struct IppDWT2D {
pub buf_fwd : *mut u8,
pub buf_bwd : *mut u8,
pub spec_fwd : *mut IppiWTFwdSpec_32f_C1R,
pub spec_bwd : *mut IppiWTInvSpec_32f_C1R
}
struct DWT2DSize {
spec_fwd : i32,
spec_bwd : i32,
buf_fwd : i32,
buf_bwd : i32
}
fn border_size(
src_width : usize,
src_height : usize,
filt_len_low : usize,
filt_len_high : usize,
anchor_low : usize,
anchor_high : usize
) -> (usize, usize) {
let left_border_low = filt_len_low - 1 - anchor_low;
let left_border_high = filt_len_high - 1 - anchor_high;
let right_border_low = anchor_low;
let right_border_high = anchor_high;
let left_top_border = left_border_low.max(left_border_high);
let right_bottom_border = right_border_low.max(right_border_high);
(left_top_border, right_bottom_border)
}
fn extended_image_size(
src_width : usize,
src_height : usize,
filt_len_low : usize,
filt_len_high : usize,
anchor_low : usize,
anchor_high : usize
) -> (usize, usize) {
let (left_top_border, right_bottom_border) = border_size(
src_width,
src_height,
filt_len_low,
filt_len_high,
anchor_low,
anchor_high
);
let src_width_with_borders = src_width + left_top_border + right_bottom_border;
let src_height_with_borders = src_height + left_top_border + right_bottom_border;
(src_width_with_borders, src_height_with_borders)
}
unsafe fn calc_state_size(
len_low : i32,
len_high : i32,
anchor_low : i32,
anchor_high : i32
) -> DWT2DSize {
let num_channels = 1;
let mut spec_fwd = 0;
let mut buf_fwd = 0;
let get_sz_status = ippiWTFwdGetSize_32f(
num_channels,
len_low,
anchor_low,
len_high,
anchor_high,
&mut spec_fwd as *mut _,
&mut buf_fwd as *mut _
);
check_status("Get fwd size", get_sz_status);
let mut spec_bwd = 0;
let mut buf_bwd = 0;
let get_sz_status = ippiWTInvGetSize_32f(
num_channels,
len_low,
anchor_low,
len_high,
anchor_high,
&mut spec_bwd as *mut _,
&mut buf_bwd as *mut _
);
check_status("Get bwd size", get_sz_status);
DWT2DSize {
spec_fwd,
buf_fwd,
spec_bwd,
buf_bwd
}
}
pub unsafe fn build_dwt2d_state(taps_low : &[f32], taps_high : &[f32]) -> IppDWT2D {
assert!(taps_low.len() == 4 && taps_high.len() == 4);
let len_low = taps_low.len() as i32;
let len_high = taps_high.len() as i32;
let anchor_low = taps_low.len() as i32 - 1; let anchor_high = taps_high.len() as i32 - 1; let sz = calc_state_size(len_low, len_high, anchor_low, anchor_high);
let spec_fwd = ippMalloc(sz.spec_fwd) as *mut IppiWTFwdSpec_32f_C1R;
let fwd_status = ippiWTFwdInit_32f_C1R(
spec_fwd,
taps_low.as_ptr(),
len_low,
anchor_low,
taps_high.as_ptr(),
len_high,
anchor_high
);
check_status("init forward", fwd_status);
let buf_fwd = ippMalloc(sz.buf_fwd) as *mut u8;
let spec_bwd = ippMalloc(sz.spec_bwd) as *mut IppiWTInvSpec_32f_C1R;
let bwd_status = ippiWTInvInit_32f_C1R(
spec_bwd,
taps_low.as_ptr(),
len_low,
anchor_low,
taps_high.as_ptr(),
len_high,
anchor_high
);
check_status("init backward", bwd_status);
let buf_bwd = ippMalloc(sz.buf_bwd) as *mut u8;
IppDWT2D { spec_fwd, spec_bwd, buf_fwd, buf_bwd }
}
struct DWTParams {
src_step_bytes : i32,
dst_step_bytes : i32,
dst_roi : IppiSize
}
impl DWTParams {
fn define(src_len : usize, src_ncol : usize, filt_len : usize) -> Self {
assert!(src_ncol % 2 == 0);
assert!(src_len / src_ncol == src_ncol);
let anchor = filt_len - 1;
let (tl_border, br_border) = border_size(src_ncol, src_ncol, filt_len, filt_len, anchor, anchor);
assert!(tl_border == 0);
assert!(br_border == filt_len - 1);
let effective_ncol = src_ncol - filt_len;
let px_stride = effective_ncol + tl_border + br_border + 1;
assert!(px_stride == src_ncol);
let src_step_bytes = ipputils::row_size_bytes::<f32>(px_stride);
let dst_step_bytes = ipputils::row_size_bytes::<f32>(effective_ncol / 2);
let dst_roi = IppiSize{ width : (effective_ncol / 2) as i32, height : (effective_ncol / 2) as i32 };
DWTParams { src_step_bytes, dst_step_bytes, dst_roi }
}
}
pub unsafe fn apply_forward(
fwd_spec : *const IppiWTFwdSpec_32f_C1R,
fwd_buf : *mut u8,
src : &[f32],
src_ncol : usize,
filt_len : usize,
approx : &mut [f32],
detail_x : &mut [f32],
detail_y : &mut [f32],
detail_xy : &mut [f32]
) {
let params = DWTParams::define(src.len(), src_ncol, filt_len);
let fwd_status = ippiWTFwd_32f_C1R (
src.as_ptr(),
params.src_step_bytes,
approx.as_mut_ptr(),
params.dst_step_bytes,
detail_x.as_mut_ptr(),
params.dst_step_bytes,
detail_y.as_mut_ptr(),
params.dst_step_bytes,
detail_xy.as_mut_ptr(),
params.dst_step_bytes,
params.dst_roi,
fwd_spec,
fwd_buf
);
check_status("apply forward", fwd_status);
}
pub unsafe fn apply_backward(
bwd_spec : *const IppiWTInvSpec_32f_C1R,
bwd_buf : *mut u8,
src : &mut [f32],
src_ncol : usize,
filt_len : usize,
approx : &[f32],
detail_x : &[f32],
detail_y : &[f32],
detail_xy : &[f32]
) {
let params = DWTParams::define(src.len(), src_ncol, filt_len);
let bwd_status = ippiWTInv_32f_C1R(
approx.as_ptr(),
params.dst_step_bytes,
detail_x.as_ptr(),
params.dst_step_bytes,
detail_y.as_ptr(),
params.dst_step_bytes,
detail_xy.as_ptr(),
params.dst_step_bytes,
params.dst_roi,
src.as_mut_ptr(),
params.src_step_bytes,
bwd_spec,
bwd_buf
);
check_status("apply backward", bwd_status);
}
#[test]
fn test_extended_image_size() {
let anchors : [usize; 4] = [0, 1, 2, 3];
let filt_len_low = 4;
let filt_len_high = 4;
for anchor in &anchors {
let (left_top, right_bottom) = border_size(64, 64, filt_len_low, filt_len_high, *anchor, *anchor);
println!("Left and top borders = {:?}; Right and bottom borders = {:?}", left_top, right_bottom);
let extended_sz = extended_image_size(64, 64, filt_len_low, filt_len_high, *anchor, *anchor);
println!("Anchor = {:?}; Extended size = {:?}", (anchor, anchor), extended_sz);
}
}