1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
extern crate imgref; 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:prev, curr:curr, next: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: next, } } } #[inline] 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 tc = row.prev[left.saturating_sub(1)]; let mut tn = row.prev[left]; let mut mp; let mut mc = row.curr[left.saturating_sub(1)]; let mut mn = row.curr[left]; let mut bp; let mut bc = row.next[left.saturating_sub(1)]; let mut bn = row.next[left]; 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, ]); }