use imgref::*;
#[derive(Copy,Clone,Debug,Eq,PartialEq)]
pub struct Triple<T> {
pub prev: T,
pub curr: T,
pub next: T,
}
impl<T> Triple<T> {
#[inline(always)]
pub fn new(prev: T, curr: T, next: T) -> Self {
Triple {prev, curr, next}
}
}
impl<T: Copy> Triple<T> {
#[inline(always)]
pub fn advance(self, next: Option<T>) -> Self {
let next = if let Some(next) = next {next} else {self.next};
Triple {
prev: self.curr,
curr: self.next,
next,
}
}
}
#[inline(always)]
pub fn loop9_img<Pixel, Callback>(img: ImgRef<'_, Pixel>, cb: Callback)
where Pixel: Copy, Callback: FnMut(usize, usize, Triple<Pixel>,Triple<Pixel>,Triple<Pixel>)
{
loop9(img, 0, 0, img.width(), img.height(), cb)
}
#[inline]
pub fn loop9<Pixel, Callback>(img: ImgRef<'_, Pixel>, left: usize, top: usize, width: usize, height: usize, mut cb: Callback)
where Pixel: Copy, Callback: FnMut(usize, usize, Triple<Pixel>,Triple<Pixel>,Triple<Pixel>)
{
let max_width = img.width();
let max_height = img.height();
let stride = img.stride();
let data = img.buf().as_ref();
let t = top * stride;
let mut row = Triple {
prev: &data[t..t+max_width],
curr: &data[t..t+max_width],
next: &data[t..t+max_width],
};
for y in top..top+height {
row = row.advance(if y+1 < max_height {let t=(y+1)*stride; Some(&data[t..t+max_width])} else {None});
let mut tp;
let mut tn = row.prev[left];
let mut tc = row.prev[left.saturating_sub(1)];
let mut mp;
let mut mn = row.curr[left];
let mut mc = row.curr[left.saturating_sub(1)];
let mut bp;
let mut bn = row.next[left];
let mut bc = row.next[left.saturating_sub(1)];
for x in left..left+width {
tp = tc;
tc = tn;
tn = if x+1 < max_width {row.prev[x+1]} else {tc};
mp = mc;
mc = mn;
mn = if x+1 < max_width {row.curr[x+1]} else {mc};
bp = bc;
bc = bn;
bn = if x+1 < max_width {row.next[x+1]} else {bc};
cb(x-left,y-top,Triple::new(tp,tc,tn),Triple::new(mp,mc,mn),Triple::new(bp,bc,bn));
}
}
}
#[test]
fn test_loop9() {
let src = vec![
1, 2, 3, 4,
5, 6, 7, 8,
9,10,11,12,
13,14,15,16,
];
let img = Img::new(src.clone(), 4, 4);
assert_eq!(4, img.width());
assert_eq!(4, img.stride());
assert_eq!(4, img.height());
let check = |l,t,w,h,exp|{
let mut res = Vec::new();
loop9(img.as_ref(), l,t,w,h, |_x,_y,_top,mid,_bot| res.push(mid.curr));
assert_eq!(exp, res);
};
check(0,0,4,4, src);
check(0,0,4,1, vec![1, 2, 3, 4]);
check(0,3,4,1, vec![13,14,15,16]);
check(0,0,3,3, vec![
1, 2, 3,
5, 6, 7,
9,10,11,
]);
check(0,0,1,1,vec![1]);
check(1,0,1,1,vec![2]);
check(2,0,1,1,vec![3]);
check(3,0,1,1,vec![4]);
check(1,0,3,4,vec![
2, 3, 4,
6, 7, 8,
10,11,12,
14,15,16,
]);
}