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,
    ]);
}