Skip to main content

bayer/demosaic/
linear.rs

1//! Demosaicing using linear interpolation.
2//!
3//! ```text
4//!   green_kernel = (1 / 4) *
5//!       [ 0 1 0
6//!       ; 1 4 1
7//!       ; 0 1 0 ];
8//!
9//!   red/blue_kernel = (1 / 4) *
10//!       [ 1 2 1
11//!       ; 2 4 2
12//!       ; 1 2 1 ];
13//! ```
14
15use std::io::Read;
16
17#[cfg(feature = "rayon")]
18use std::slice;
19
20#[cfg(feature = "rayon")]
21use rayon::prelude::*;
22
23use ::{BayerDepth,BayerError,BayerResult,CFA,RasterMut};
24use bayer::{BayerRead8,BayerRead16};
25use border_replicate::*;
26use demosaic::check_depth;
27
28const PADDING: usize = 1;
29
30pub fn run(r: &mut Read,
31        depth: BayerDepth, cfa: CFA, dst: &mut RasterMut)
32        -> BayerResult<()> {
33    if dst.w < 2 || dst.h < 2 {
34        return Err(BayerError::WrongResolution);
35    }
36    if !check_depth(depth, dst.depth) {
37        return Err(BayerError::WrongDepth);
38    }
39
40    match depth {
41        BayerDepth::Depth8 => debayer_u8(r, cfa, dst),
42        BayerDepth::Depth16BE => debayer_u16(r, true, cfa, dst),
43        BayerDepth::Depth16LE => debayer_u16(r, false, cfa, dst),
44    }
45}
46
47macro_rules! apply_kernel_row {
48    ($T:ty; $row:ident, $prev:expr, $curr:expr, $next:expr, $cfa:expr, $w:expr) => {{
49        let (mut i, cfa_c, cfa_g) =
50            if $cfa == CFA::BGGR || $cfa == CFA::RGGB {
51                (0, $cfa, $cfa.next_x())
52            } else {
53                apply_kernel_g!($T; $row, $prev, $curr, $next, $cfa, 0);
54                (1, $cfa.next_x(), $cfa)
55            };
56
57        while i + 1 < $w {
58            apply_kernel_c!($T; $row, $prev, $curr, $next, cfa_c, i);
59            apply_kernel_g!($T; $row, $prev, $curr, $next, cfa_g, i + 1);
60            i = i + 2;
61        }
62
63        if i < $w {
64            apply_kernel_c!($T; $row, $prev, $curr, $next, cfa_c, i);
65        }
66    }}
67}
68
69macro_rules! apply_kernel_c {
70    ($T:ty; $row:ident, $prev:expr, $curr:expr, $next:expr, $cfa:expr, $i:expr) => {{
71        // current = B/R, diagonal = R/B.
72        let (c, d) = if $cfa == CFA::BGGR { (2, 0) } else { (0, 2) };
73        let j = $i + PADDING;
74
75        $row[3 * $i + c] = $curr[j];
76        $row[3 * $i + 1]
77            = ((  $prev[j] as u32
78                + $curr[j - 1] as u32 + $curr[j + 1] as u32
79                + $next[j] as u32) / 4) as $T;
80        $row[3 * $i + d]
81            = ((  $prev[j - 1] as u32 + $prev[j + 1] as u32
82                + $next[j - 1] as u32 + $next[j + 1] as u32) / 4) as $T;
83    }}
84}
85
86macro_rules! apply_kernel_g {
87    ($T:ty; $row:ident, $prev:expr, $curr:expr, $next:expr, $cfa:expr, $i:expr) => {{
88        // horizontal = B/R, vertical = R/G.
89        let (h, v) = if $cfa == CFA::GBRG { (2, 0) } else { (0, 2) };
90        let j = $i + PADDING;
91
92        $row[3 * $i + h]
93            = (($curr[j - 1] as u32 + $curr[j + 1] as u32) / 2) as $T;
94        $row[3 * $i + 1] = $curr[j];
95        $row[3 * $i + v]
96            = (($prev[j] as u32 + $next[j] as u32) / 2) as $T;
97    }}
98}
99
100/*--------------------------------------------------------------*/
101/* Rayon                                                        */
102/*--------------------------------------------------------------*/
103
104#[cfg(feature = "rayon")]
105fn debayer_u8(r: &mut Read, cfa: CFA, dst: &mut RasterMut)
106        -> BayerResult<()> {
107    let (w, h) = (dst.w, dst.h);
108    let mut data = vec![0u8; (2 * PADDING + w) * (2 * PADDING + h)];
109
110    // Read all data.
111    {
112        let stride = 2 * PADDING + w;
113        let rdr = BorderReplicate8::new(w, PADDING);
114
115        for mut row in data.chunks_mut(stride).skip(PADDING).take(h) {
116            rdr.read_line(r, &mut row)?;
117        }
118
119        {
120            let (top, src) = data.split_at_mut(stride * PADDING);
121            top[(stride * 0)..(stride * 1)].copy_from_slice(
122                    &src[(stride * 1)..(stride * 2)]);
123        }
124
125        {
126            let (src, bottom) = data.split_at_mut(stride * (h + PADDING));
127            let yy = PADDING + h;
128            bottom[(stride * 0)..(stride * 1)].copy_from_slice(
129                    &src[(stride * (yy - 2))..(stride * (yy - 1))]);
130        }
131    }
132
133    dst.buf.par_chunks_mut(dst.stride).enumerate()
134            .for_each(|(y, mut row)| {
135        let stride = 2 * PADDING + w;
136        let prev = &data[(stride * (PADDING + y - 1)) .. (stride * (PADDING + y + 0))];
137        let curr = &data[(stride * (PADDING + y + 0)) .. (stride * (PADDING + y + 1))];
138        let next = &data[(stride * (PADDING + y + 1)) .. (stride * (PADDING + y + 2))];
139        let cfa_y = if y % 2 == 0 { cfa } else { cfa.next_y() };
140
141        apply_kernel_row!(u8; row, prev, curr, next, cfa_y, w);
142    });
143
144    Ok(())
145}
146
147#[cfg(feature = "rayon")]
148fn debayer_u16(r: &mut Read, be: bool, cfa: CFA, dst: &mut RasterMut)
149        -> BayerResult<()> {
150    let (w, h) = (dst.w, dst.h);
151    let mut data = vec![0u16; (2 * PADDING + w) * (2 * PADDING + h)];
152
153    // Read all data.
154    {
155        let stride = 2 * PADDING + w;
156        let rdr: Box<BayerRead16> = if be {
157            Box::new(BorderReplicate16BE::new(w, PADDING))
158        } else {
159            Box::new(BorderReplicate16LE::new(w, PADDING))
160        };
161
162        for mut row in data.chunks_mut(stride).skip(PADDING).take(h) {
163            rdr.read_line(r, &mut row)?;
164        }
165
166        {
167            let (top, src) = data.split_at_mut(stride * PADDING);
168            top[(stride * 0)..(stride * 1)].copy_from_slice(
169                    &src[(stride * 1)..(stride * 2)]);
170        }
171
172        {
173            let (src, bottom) = data.split_at_mut(stride * (h + PADDING));
174            let yy = PADDING + h;
175            bottom[(stride * 0)..(stride * 1)].copy_from_slice(
176                    &src[(stride * (yy - 2))..(stride * (yy - 1))]);
177        }
178    }
179
180    dst.buf.par_chunks_mut(dst.stride).enumerate()
181            .for_each(|(y, mut row)| {
182        let stride = 2 * PADDING + w;
183        let prev = &data[(stride * (PADDING + y - 1)) .. (stride * (PADDING + y + 0))];
184        let curr = &data[(stride * (PADDING + y + 0)) .. (stride * (PADDING + y + 1))];
185        let next = &data[(stride * (PADDING + y + 1)) .. (stride * (PADDING + y + 2))];
186        let cfa_y = if y % 2 == 0 { cfa } else { cfa.next_y() };
187
188        let row16 = unsafe{ slice::from_raw_parts_mut(row.as_mut_ptr() as *mut u16, row.len() / 2) };
189        apply_kernel_row!(u16; row16, prev, curr, next, cfa_y, w);
190    });
191
192    Ok(())
193}
194
195/*--------------------------------------------------------------*/
196/* Naive                                                        */
197/*--------------------------------------------------------------*/
198
199#[cfg(not(feature = "rayon"))]
200fn debayer_u8(r: &mut Read, cfa: CFA, dst: &mut RasterMut)
201        -> BayerResult<()> {
202    let (w, h) = (dst.w, dst.h);
203    let mut prev = vec![0u8; 2 * PADDING + w];
204    let mut curr = vec![0u8; 2 * PADDING + w];
205    let mut next = vec![0u8; 2 * PADDING + w];
206    let mut cfa = cfa;
207
208    let rdr = BorderReplicate8::new(w, PADDING);
209    rdr.read_line(r, &mut curr)?;
210    rdr.read_line(r, &mut next)?;
211
212    {   // y = 0.
213        let row = dst.borrow_row_u8_mut(0);
214        apply_kernel_row!(u8; row, next, curr, next, cfa, w);
215        cfa = cfa.next_y();
216    }
217
218    for y in 1..(h - 1) {
219        rotate!(prev <- curr <- next);
220        rdr.read_line(r, &mut next)?;
221
222        let row = dst.borrow_row_u8_mut(y);
223        apply_kernel_row!(u8; row, prev, curr, next, cfa, w);
224        cfa = cfa.next_y();
225    }
226
227    {   // y = h - 1.
228        let row = dst.borrow_row_u8_mut(h - 1);
229        apply_kernel_row!(u8; row, curr, next, curr, cfa, w);
230    }
231
232    Ok(())
233}
234
235#[cfg(not(feature = "rayon"))]
236fn debayer_u16(r: &mut Read, be: bool, cfa: CFA, dst: &mut RasterMut)
237        -> BayerResult<()> {
238    let (w, h) = (dst.w, dst.h);
239    let mut prev = vec![0u16; 2 * PADDING + w];
240    let mut curr = vec![0u16; 2 * PADDING + w];
241    let mut next = vec![0u16; 2 * PADDING + w];
242    let mut cfa = cfa;
243
244    let rdr: Box<BayerRead16> = if be {
245        Box::new(BorderReplicate16BE::new(w, PADDING))
246    } else {
247        Box::new(BorderReplicate16LE::new(w, PADDING))
248    };
249    rdr.read_line(r, &mut curr)?;
250    rdr.read_line(r, &mut next)?;
251
252    {   // y = 0.
253        let row = dst.borrow_row_u16_mut(0);
254        apply_kernel_row!(u16; row, next, curr, next, cfa, w);
255        cfa = cfa.next_y();
256    }
257
258    for y in 1..(h - 1) {
259        rotate!(prev <- curr <- next);
260        rdr.read_line(r, &mut next)?;
261
262        let row = dst.borrow_row_u16_mut(y);
263        apply_kernel_row!(u16; row, prev, curr, next, cfa, w);
264        cfa = cfa.next_y();
265    }
266
267    {   // y = h - 1.
268        let row = dst.borrow_row_u16_mut(h - 1);
269        apply_kernel_row!(u16; row, curr, next, curr, cfa, w);
270    }
271
272    Ok(())
273}
274
275#[cfg(test)]
276mod tests {
277    use std::io::Cursor;
278    use ::{CFA,RasterDepth,RasterMut};
279    use super::debayer_u8;
280
281    #[test]
282    fn test_even() {
283        // R: set.seed(0); matrix(floor(runif(n=16, min=0, max=256)), nrow=4, byrow=TRUE)
284        let src = [
285            229, 67, 95,146,
286            232, 51,229,241,
287            169,161, 15, 52,
288             45,175, 98,197 ];
289
290        let expected = [
291            229,149, 51,  162, 67, 51,   95,167,146,   95,146,241,
292            199,232, 51,  127,172, 51,   55,229,146,   55,164,241,
293            169,149,113,   92,161,113,   15,135,166,   15, 52,219,
294            169, 45,175,   92,116,175,   15, 98,186,   15, 75,197 ];
295
296        const IMG_W: usize = 4;
297        const IMG_H: usize = 4;
298        let mut dst = [0u8; 3 * IMG_W * IMG_H];
299
300        let res = debayer_u8(&mut Cursor::new(&src[..]), CFA::RGGB,
301                &mut RasterMut::new(IMG_W, IMG_H, RasterDepth::Depth8, &mut dst[..]));
302        assert!(res.is_ok());
303        assert_eq!(&dst[..], &expected[..]);
304    }
305
306    #[test]
307    fn test_odd() {
308        // R: set.seed(0); matrix(floor(runif(n=9, min=0, max=256)), nrow=3, byrow=TRUE)
309        let src = [
310            229, 67, 95,
311            146,232, 51,
312            229,241,169 ];
313
314        let expected = [
315            229,106,232,  162, 67,232,   95, 59,232,
316            229,146,232,  180,126,232,  132, 51,232,
317            229,193,232,  199,241,232,  169,146,232 ];
318
319        const IMG_W: usize = 3;
320        const IMG_H: usize = 3;
321        let mut buf = [0u8; 3 * IMG_W * IMG_H];
322
323        let res = debayer_u8(&mut Cursor::new(&src[..]), CFA::RGGB,
324                &mut RasterMut::new(IMG_W, IMG_H, RasterDepth::Depth8, &mut buf));
325        assert!(res.is_ok());
326        assert_eq!(&buf[..], &expected[..]);
327    }
328}