libopenraw
bimedian_demosaic.cpp
1 /*
2  * libopenraw - demoisaic.cpp
3  *
4  * This library is free software: you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation, either version 3 of
7  * the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see
16  * <http://www.gnu.org/licenses/>.
17  *
18  * This code has been adapted from GEGL:
19  * Copyright 2006 Øyvind Kolås <pippin@gimp.org>
20  * Copyright 2008 Bradley Broom <bmbroom@gmail.com>
21  *
22  * In libopenraw:
23  * Copyright 2008-2009 Hubert Figuiere <hub@figuiere.net>
24  * Copyright 2008 Novell Inc.
25  */
26 
27 #include <stdlib.h>
28 
29 #include <algorithm>
30 
31 #include <libopenraw/demosaic.h>
32 
33 void bimedian_demosaic (uint16_t *src, uint32_t src_x, uint32_t src_y,
34  or_cfa_pattern pattern, uint8_t *dst);
35 
36 /*
37 extern "C" void or_demosaic(uint16_t*, uint32_t, uint32_t, or_cfa_pattern, uint8_t*)
38 {
39 }
40 */
41 
42 /* Returns the median of four floats. We define the median as the average of
43  * the central two elements.
44  */
45 static inline float
46 m4 (float a, float b, float c, float d)
47 {
48  float t;
49 
50  /* Sort ab */
51  if (a > b)
52  {
53  t = b;
54  b = a;
55  a = t;
56  }
57  /* Sort abc */
58  if (b > c)
59  {
60  t = c;
61  c = b;
62  if (a > t)
63  {
64  b = a;
65  a = t;
66  }
67  else
68  b = t;
69  }
70  /* Return average of central two elements. */
71  if (d >= c) /* Sorted order would be abcd */
72  return (b + c) / 2.0;
73  else if (d >= a) /* Sorted order would be either abdc or adbc */
74  return (b + d) / 2.0;
75  else /* Sorted order would be dabc */
76  return (a + b) / 2.0;
77 }
78 
79 /* Defines to make the row/col offsets below obvious. */
80 #define ROW src_x
81 #define COL 1
82 
83 /* We expect src_extent to have a one pixel border around all four sides
84  * of dst_extent.
85  */
86 void
87 bimedian_demosaic (uint16_t *src, uint32_t src_x, uint32_t src_y,
88  or_cfa_pattern pattern, uint8_t *dst)
89 {
90  uint32_t x,y;
91  uint32_t offset, doffset;
92  float *src_buf;
93  float *dst_buf;
94 
95  int npattern = 0;
96  switch(pattern) {
97  case OR_CFA_PATTERN_GRBG:
98  npattern = 0;
99  break;
100  case OR_CFA_PATTERN_BGGR:
101  npattern = 1;
102  break;
103  case OR_CFA_PATTERN_GBRG:
104  npattern = 2;
105  break;
106  case OR_CFA_PATTERN_RGGB:
107  npattern = 3;
108  break;
109  default:
110  break;
111  }
112 
113  src_buf = (float*)calloc(src_x * src_y, sizeof(float));
114  dst_buf = (float*)calloc(src_x * src_y * 3, sizeof(float));
115 
116  std::copy(src, src + (src_x * src_y), src_buf);
117 
118  offset = ROW + COL;
119  doffset = 0;
120  for(y = 1 ; y < src_y - 1; y++)
121  {
122  for (x = 1 ; x < src_x - 1; x++)
123  {
124  float red=0.0;
125  float green=0.0;
126  float blue=0.0;
127 
128  if ((y + npattern%2)%2==0) {
129  if ((x+npattern/2)%2==1) {
130  /* GRG
131  * BGB
132  * GRG
133  */
134  blue =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
135  green=src_buf[offset];
136  red =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
137  }
138  else {
139  /* RGR
140  * GBG
141  * RGR
142  */
143  blue =src_buf[offset];
144  green=m4(src_buf[offset-ROW], src_buf[offset-COL],
145  src_buf[offset+COL], src_buf[offset+ROW]);
146  red =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
147  src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
148  }
149  }
150  else {
151  if ((x+npattern/2)%2==1) {
152  /* BGB
153  * GRG
154  * BGB
155  */
156  blue =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
157  src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
158  green=m4(src_buf[offset-ROW], src_buf[offset-COL],
159  src_buf[offset+COL], src_buf[offset+ROW]);
160  red =src_buf[offset];
161  }
162  else {
163  /* GBG
164  * RGR
165  * GBG
166  */
167  blue =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
168  green=src_buf[offset];
169  red =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
170  }
171  }
172 
173  dst_buf [doffset*3+0] = red / 16.0;
174  dst_buf [doffset*3+1] = green / 16.0;
175  dst_buf [doffset*3+2] = blue / 16.0;
176 
177  offset++;
178  doffset++;
179  }
180  offset+=2;
181  }
182  std::copy(dst_buf, dst_buf + (src_x * src_y * 3), dst);
183  free(src_buf);
184  free(dst_buf);
185 }
186 
187 
188 
189 /*
190  Local Variables:
191  mode:c++
192  c-file-style:"stroustrup"
193  c-file-offsets:((innamespace . 0))
194  indent-tabs-mode:nil
195  fill-column:80
196  End:
197 */