use nalgebra::*;
use nalgebra::base::storage::Storage;
use std::convert::TryInto;
use crate::image::*;
use super::*;
use crate::dwt::dwt2d::*;
use crate::dwt::is_valid_dwt_len;
#[derive(Clone, Copy)]
pub(crate) enum DWTFilter {
Vertical, Horizontal, Both }
pub(crate) struct DWTIteratorBase<S> {
max_lvl : usize,
curr_lvl : usize,
region : DWTFilter,
full : S
}
impl<'a, N> DWTIteratorBase<&'a ImagePyramid<N>>
where
N : Scalar + Copy
{
pub fn new_ref(
full : &'a ImagePyramid<N>
) -> DWTIteratorBase<&'a ImagePyramid<N>>
where
N : Scalar + Copy
{
let max_lvl = calc_max_level(full.as_ref());
DWTIteratorBase::<&'a ImagePyramid<N>> {
max_lvl,
curr_lvl : 0,
region : DWTFilter::Vertical,
full
}
}
}
pub(crate) type DWTIterator2D<'a, N> = DWTIteratorBase<&'a ImagePyramid<N>>;
impl<'a, N> DWTIterator2D<'a, N>
where
N : Scalar + Copy
{
pub fn new(full : &'a ImagePyramid<N>) -> Self {
let max_lvl = calc_max_level(full.as_ref());
DWTIterator2D{ max_lvl, curr_lvl : 0, region : DWTFilter::Vertical, full }
}
}
impl<'a, N> Iterator for DWTIterator2D<'a, N>
where
N : Scalar + Copy
{
type Item = ImageLevel<'a, N>;
fn next(&mut self) -> Option<ImageLevel<'a, N>> {
let ans = get_level_slice_2d(self.full, self.curr_lvl, self.region)?;
if self.curr_lvl == self.max_lvl + 1 {
return None;
}
if self.curr_lvl == 0 {
self.curr_lvl += 1;
} else {
let (new_region, new_lvl) = match self.region {
DWTFilter::Vertical => {
(DWTFilter::Both, self.curr_lvl)
},
DWTFilter::Both => {
(DWTFilter::Horizontal, self.curr_lvl)
},
DWTFilter::Horizontal => {
(DWTFilter::Vertical, self.curr_lvl + 1)
}
};
self.region = new_region;
self.curr_lvl = new_lvl;
}
Some(ans)
}
}
fn define_level_bounds(lvl : usize, region : DWTFilter) -> ((usize, usize), (usize, usize)) {
let lvl_pow = (2 as i32).pow(lvl.try_into().unwrap()) as usize;
let region_offset = match region {
DWTFilter::Both => (lvl_pow, lvl_pow),
DWTFilter::Vertical => (lvl_pow as usize, 0),
DWTFilter::Horizontal => (0, lvl_pow as usize)
};
match lvl {
0 => ((0, 0), (2, 2)),
_ => (region_offset, (lvl_pow, lvl_pow))
}
}
pub fn calc_max_level<N>(full : &[N]) -> usize {
let side = (full.len() as f32).sqrt() as usize;
assert!(is_valid_dwt_len(side));
let max_lvl = ((side as f32).log2() - 1.) as usize;
max_lvl
}
fn get_level_slice_2d<'a, N>(
m : &'a ImagePyramid<N>,
lvl : usize,
region : DWTFilter
) -> Option<ImageLevel<'a, N>>
where
N : Scalar + Copy
{
let (off, bounds) = define_level_bounds(lvl, region);
let img : &'a Image<_> = m.as_ref();
let nrows = img.height();
if bounds.0 > nrows / 2 {
return None;
}
Some(ImageLevel::<'a, N>::from(img.window(off, bounds).unwrap()))
}
#[test]
fn dwt_iter_1d() {
let d = DVector::from_row_slice(
&[0., 0., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.]
);
let mut iter = DWTIterator1D::new_ref(&d);
while let Some(s) = iter.next() {
println!("{}", s);
}
}
#[test]
fn dwt_iter_2d() {
let d = DMatrix::from_row_slice(16, 16,
&[0., 0., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
0., 0., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
2., 2., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
2., 2., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
2., 2., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
2., 2., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.,
]);
let mut iter = DWTIterator2D::new_ref(&d);
while let Some(s) = iter.next() {
println!("{}", s);
}
}
#[test]
fn dwt_iter_64() {
let m = DMatrix::zeros(64,64);
let mut iter = DWTIterator2D::new_ref(&m);
while let Some(s) = iter.next() {
println!("{}", s);
}
}