Skip to main content

bayer/demosaic/
none.rs

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