imagepipe/ops/
demosaic.rs1use crate::opbasics::*;
2
3#[derive(Clone, Debug, Serialize, Deserialize)]
4pub struct OpDemosaic {
5 pub cfa: String,
6}
7
8impl OpDemosaic {
9 pub fn new(img: &ImageSource) -> OpDemosaic {
10 match img {
11 ImageSource::Raw(img) => {
12 OpDemosaic{
13 cfa: img.cropped_cfa().to_string(),
14 }
15 },
16 ImageSource::Other(_) => {
17 OpDemosaic{
18 cfa: "".to_string(),
19 }
20 }
21 }
22 }
23}
24
25impl<'a> ImageOp<'a> for OpDemosaic {
26 fn name(&self) -> &str {"demosaic"}
27 fn run(&self, pipeline: &PipelineGlobals, buf: Arc<OpBuffer>) -> Arc<OpBuffer> {
28 let nwidth = pipeline.settings.demosaic_width;
29 let nheight = pipeline.settings.demosaic_height;
30 let scale = crate::scaling::calculate_scale(buf.width, buf.height, nwidth, nheight);
31
32 let cfa = CFA::new(&self.cfa);
33 let minscale = match cfa.width {
34 2 => 2.0, 6 => 3.0, 8 => 2.0, 12 => 12.0, _ => 2.0, };
40
41 if scale <= 1.0 && buf.colors == 4 {
42 buf
44 } else if buf.colors == 4 {
45 Arc::new(crate::scaling::scale_down_opbuf(&buf, nwidth, nheight))
47 } else if scale >= minscale {
48 Arc::new(crate::scaling::scaled_demosaic(cfa, &buf, nwidth, nheight))
51 } else {
52 let fullsize = full(cfa, &buf);
55 if scale > 1.0 {
56 Arc::new(crate::scaling::scale_down_opbuf(&fullsize, nwidth, nheight))
57 } else {
58 Arc::new(fullsize)
59 }
60 }
61 }
62
63 }
66
67pub fn full(cfa: CFA, buf: &OpBuffer) -> OpBuffer {
68 let mut out = OpBuffer::new(buf.width, buf.height, 4, buf.monochrome);
69
70 let offsets3x3: [(isize,isize);9] = [
71 (-1,-1), (-1, 0), (-1, 1),
72 ( 0,-1), ( 0, 0), ( 0, 1),
73 ( 1,-1), ( 1, 0), ( 1, 1),
74 ];
75
76 let mut lookups = [[[0;9];48];48];
78 for (row, line) in lookups.iter_mut().enumerate() {
79 for (col, colors) in line.iter_mut().enumerate() {
80 let pixcolor = cfa.color_at(row, col);
81
82 for (i, o) in offsets3x3.iter().enumerate() {
83 let (dy, dx) = *o;
84 let row = (48+dy) as usize + row;
85 let col = (48+dx) as usize + col;
86 let ocolor = cfa.color_at(row, col);
87 colors[i] = if ocolor != pixcolor || (dx == 0 && dy == 0) { ocolor } else { 4 };
88 }
89 }
90 }
91
92 out.mutate_lines(&(|line: &mut [f32], row| {
94 for (col, pix) in line.chunks_exact_mut(4).enumerate() {
95 let ref colors = lookups[row%48][col%48];
96 let mut sums = [0f32;5];
97 let mut counts = [0f32;5];
98
99 for (i, o) in offsets3x3.iter().enumerate() {
100 let (dy, dx) = *o;
101 let row = row as isize + dy;
102 let col = col as isize + dx;
103 if row >= 0 && row < (buf.height as isize) &&
104 col >= 0 && col < (buf.width as isize) {
105 sums[colors[i]] += buf.data[(row as usize)*buf.width+(col as usize)];
106 counts[colors[i]] += 1.0;
107 }
108 }
109
110 for c in 0..4 {
111 if counts[c] > 0.0 {
112 pix[c] = sums[c] / counts[c];
113 }
114 }
115 }
116 }));
117
118 out
119}