Skip to main content

bayer/demosaic/
nearestneighbour.rs

1//! Demosaicing using nearest neighbour interpolation.
2
3use std::io::Read;
4
5use ::{BayerDepth,BayerError,BayerResult,CFA,RasterMut};
6use bayer::{BayerRead8,BayerRead16};
7use border_replicate::*;
8use demosaic::check_depth;
9
10const PADDING: usize = 1;
11
12pub fn run(r: &mut Read,
13        depth: BayerDepth, cfa: CFA, dst: &mut RasterMut)
14        -> BayerResult<()> {
15    if dst.w < 2 || dst.h < 2 {
16        return Err(BayerError::WrongResolution);
17    }
18    if !check_depth(depth, dst.depth) {
19        return Err(BayerError::WrongDepth);
20    }
21
22    match depth {
23        BayerDepth::Depth8 => debayer_u8(r, cfa, dst),
24        BayerDepth::Depth16BE => debayer_u16(r, true, cfa, dst),
25        BayerDepth::Depth16LE => debayer_u16(r, false, cfa, dst),
26    }
27}
28
29macro_rules! apply_kernel_row {
30    ($row:ident, $prev:expr, $curr:expr, $cfa:expr, $w:expr) => {{
31        let (mut i, cfa_c, cfa_g) =
32            if $cfa == CFA::BGGR || $cfa == CFA::RGGB {
33                (0, $cfa, $cfa.next_x())
34            } else {
35                apply_kernel_g!($row, $prev, $curr, $cfa, 0);
36                (1, $cfa.next_x(), $cfa)
37            };
38
39        while i + 1 < $w {
40            apply_kernel_c!($row, $prev, $curr, cfa_c, i);
41            apply_kernel_g!($row, $prev, $curr, cfa_g, i + 1);
42            i = i + 2;
43        }
44
45        if i < $w {
46            apply_kernel_c!($row, $prev, $curr, cfa_c, i);
47        }
48    }}
49}
50
51macro_rules! apply_kernel_c {
52    ($row:ident, $prev:expr, $curr:expr, $cfa:expr, $i:expr) => {{
53        // current = B/R, diagonal = R/B.
54        let (c, d) = if $cfa == CFA::BGGR { (2, 0) } else { (0, 2) };
55        let j = $i + PADDING;
56
57        $row[3 * $i + c] = $curr[j];
58        $row[3 * $i + 1] = $curr[j - 1];
59        $row[3 * $i + d] = $prev[j - 1];
60    }}
61}
62
63macro_rules! apply_kernel_g {
64    ($row:ident, $prev:expr, $curr:expr, $cfa:expr, $i:expr) => {{
65        // horizontal = B/R, vertical = R/G.
66        let (h, v) = if $cfa == CFA::GBRG { (2, 0) } else { (0, 2) };
67        let j = $i + PADDING;
68
69        $row[3 * $i + h] = $curr[j - 1];
70        $row[3 * $i + 1] = $curr[j];
71        $row[3 * $i + v] = $prev[j];
72    }}
73}
74
75/*--------------------------------------------------------------*/
76
77fn debayer_u8(r: &mut Read, cfa: CFA, dst: &mut RasterMut)
78        -> BayerResult<()> {
79    let (w, h) = (dst.w, dst.h);
80    let mut prev = vec![0u8; 2 * PADDING + w];
81    let mut curr = vec![0u8; 2 * PADDING + w];
82    let mut cfa = cfa;
83
84    let rdr = BorderReplicate8::new(w, PADDING);
85    rdr.read_line(r, &mut prev)?;
86    rdr.read_line(r, &mut curr)?;
87
88    {   // y = 0.
89        let row = dst.borrow_row_u8_mut(0);
90        apply_kernel_row!(row, curr, prev, cfa, w);
91        cfa = cfa.next_y();
92    }
93
94    {   // y = 1.
95        let row = dst.borrow_row_u8_mut(1);
96        apply_kernel_row!(row, prev, curr, cfa, w);
97        cfa = cfa.next_y();
98    }
99
100    for y in 2..h {
101        rotate!(prev <- curr);
102        rdr.read_line(r, &mut curr)?;
103
104        let row = dst.borrow_row_u8_mut(y);
105        apply_kernel_row!(row, prev, curr, cfa, w);
106        cfa = cfa.next_y();
107    }
108
109    Ok(())
110}
111
112fn debayer_u16(r: &mut Read, be: bool, cfa: CFA, dst: &mut RasterMut)
113        -> BayerResult<()> {
114    let (w, h) = (dst.w, dst.h);
115    let mut prev = vec![0u16; 2 * PADDING + w];
116    let mut curr = vec![0u16; 2 * PADDING + w];
117    let mut cfa = cfa;
118
119    let rdr: Box<BayerRead16> = if be {
120        Box::new(BorderReplicate16BE::new(w, PADDING))
121    } else {
122        Box::new(BorderReplicate16LE::new(w, PADDING))
123    };
124    rdr.read_line(r, &mut prev)?;
125    rdr.read_line(r, &mut curr)?;
126
127    {   // y = 0.
128        let row = dst.borrow_row_u16_mut(0);
129        apply_kernel_row!(row, curr, prev, cfa, w);
130        cfa = cfa.next_y();
131    }
132
133    {   // y = 1.
134        let row = dst.borrow_row_u16_mut(1);
135        apply_kernel_row!(row, prev, curr, cfa, w);
136        cfa = cfa.next_y();
137    }
138
139    for y in 2..h {
140        rotate!(prev <- curr);
141        rdr.read_line(r, &mut curr)?;
142
143        let row = dst.borrow_row_u16_mut(y);
144        apply_kernel_row!(row, prev, curr, cfa, w);
145        cfa = cfa.next_y();
146    }
147
148    Ok(())
149}
150
151#[cfg(test)]
152mod tests {
153    use std::io::Cursor;
154    use ::{CFA,RasterDepth,RasterMut};
155    use super::debayer_u8;
156
157    #[test]
158    fn test_even() {
159        // R: set.seed(0); matrix(floor(runif(n=16, min=0, max=256)), nrow=4, byrow=TRUE)
160        let src = [
161            229, 67, 95,146,
162            232, 51,229,241,
163            169,161, 15, 52,
164             45,175, 98,197 ];
165
166        let expected = [
167            229, 67, 51,  229, 67, 51,   95, 67, 51,   95,146,241,
168            229,232, 51,  229,232, 51,   95,229, 51,   95,229,241,
169            169,161, 51,  169,161, 51,   15,161, 51,   15, 52,241,
170            169, 45,175,  169, 45,175,   15, 98,175,   15, 98,197 ];
171
172        const IMG_W: usize = 4;
173        const IMG_H: usize = 4;
174        let mut buf = [0u8; 3 * IMG_W * IMG_H];
175
176        let res = debayer_u8(&mut Cursor::new(&src[..]), CFA::RGGB,
177                &mut RasterMut::new(IMG_W, IMG_H, RasterDepth::Depth8, &mut buf));
178        assert!(res.is_ok());
179        assert_eq!(&buf[..], &expected[..]);
180    }
181
182    #[test]
183    fn test_odd() {
184        // R: set.seed(0); matrix(floor(runif(n=9, min=0, max=256)), nrow=3, byrow=TRUE)
185        let src = [
186            229, 67, 95,
187            146,232, 51,
188            229,241,169 ];
189
190        let expected = [
191            229, 67,232,  229, 67,232,   95, 67,232,
192            229,146,232,  229,146,232,   95, 51,232,
193            229,241,232,  229,241,232,  169,241,232 ];
194
195        const IMG_W: usize = 3;
196        const IMG_H: usize = 3;
197        let mut buf = [0u8; 3 * IMG_W * IMG_H];
198
199        let res = debayer_u8(&mut Cursor::new(&src[..]), CFA::RGGB,
200                &mut RasterMut::new(IMG_W, IMG_H, RasterDepth::Depth8, &mut buf));
201        assert!(res.is_ok());
202        assert_eq!(&buf[..], &expected[..]);
203    }
204}