libgphoto2 photo camera library (libgphoto2) Internals  2.5.26
bayer.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include "bayer.h"
33 
35 #include <gphoto2/gphoto2-result.h>
36 
37 static const int tile_colours[8][4] = {
38  {0, 1, 1, 2},
39  {1, 0, 2, 1},
40  {2, 1, 1, 0},
41  {1, 2, 0, 1},
42  {0, 1, 1, 2},
43  {1, 0, 2, 1},
44  {2, 1, 1, 0},
45  {1, 2, 0, 1}};
46 
47 #define RED 0
48 #define GREEN 1
49 #define BLUE 2
50 
51 static int
52 gp_bayer_accrue (unsigned char *image, int w, int h, int x0, int y0,
53  int x1, int y1, int x2, int y2, int x3, int y3, int colour);
54 
74 int
75 gp_bayer_expand (unsigned char *input, int w, int h, unsigned char *output,
76  BayerTile tile)
77 {
78  int x, y, i;
79  int colour, bayer;
80  unsigned char *ptr = input;
81 
82  gp_log (GP_LOG_DEBUG, "bayer", "w=%d, h=%d\n", w, h);
83  switch (tile) {
84 
85  case BAYER_TILE_RGGB:
86  case BAYER_TILE_GRBG:
87  case BAYER_TILE_BGGR:
88  case BAYER_TILE_GBRG:
89 
90  for (y = 0; y < h; ++y)
91  for (x = 0; x < w; ++x, ++ptr) {
92  bayer = (x&1?0:1) + (y&1?0:2);
93 
94  colour = tile_colours[tile][bayer];
95 
96  i = (y * w + x) * 3;
97 
98  output[i+RED] = 0;
99  output[i+GREEN] = 0;
100  output[i+BLUE] = 0;
101  output[i+colour] = *ptr;
102  }
103  break;
104 
109 
110 
111  for (y = 0; y < h; ++y, ptr+=w)
112  for (x = 0; x < w; ++x) {
113  bayer = (x&1?0:1) + (y&1?0:2);
114 
115  colour = tile_colours[tile][bayer];
116 
117  i = (y * w + x) * 3;
118 
119  output[i+RED] = 0;
120  output[i+GREEN] = 0;
121  output[i+BLUE] = 0;
122  output[i+colour] = (x&1)? ptr[x>>1]:ptr[(w>>1)+(x>>1)];
123  }
124  break;
125  }
126 
127  return (GP_OK);
128 }
129 
130 #define AD(x, y, w) ((y)*(w)*3+3*(x))
131 
146 int
147 gp_bayer_interpolate (unsigned char *image, int w, int h, BayerTile tile)
148 {
149  int x, y, bayer;
150  int p0, p1, p2;
151  int value, div ;
152 
153  if (w < 2 || h < 2) return GP_ERROR;
154 
155  switch (tile) {
156  default:
157  case BAYER_TILE_RGGB:
159  p0 = 0; p1 = 1; p2 = 2;
160  break;
161  case BAYER_TILE_GRBG:
163  p0 = 1; p1 = 0; p2 = 3;
164  break;
165  case BAYER_TILE_BGGR:
167  p0 = 3; p1 = 2; p2 = 1;
168  break;
169  case BAYER_TILE_GBRG:
171  p0 = 2; p1 = 3; p2 = 0;
172  break;
173  }
174 
175  for (y = 0; y < h; y++)
176  for (x = 0; x < w; x++) {
177  bayer = (x&1?0:1) + (y&1?0:2);
178 
179  if ( bayer == p0 ) {
180 
181  /* red. green lrtb, blue diagonals */
182  image[AD(x,y,w)+GREEN] =
183  gp_bayer_accrue(image, w, h, x-1, y, x+1, y, x, y-1, x, y+1, GREEN) ;
184 
185  image[AD(x,y,w)+BLUE] =
186  gp_bayer_accrue(image, w, h, x+1, y+1, x-1, y-1, x-1, y+1, x+1, y-1, BLUE) ;
187 
188  } else if (bayer == p1) {
189 
190  /* green. red lr, blue tb */
191  div = value = 0;
192  if (x < (w - 1)) {
193  value += image[AD(x+1,y,w)+RED];
194  div++;
195  }
196  if (x) {
197  value += image[AD(x-1,y,w)+RED];
198  div++;
199  }
200  image[AD(x,y,w)+RED] = value / div;
201 
202  div = value = 0;
203  if (y < (h - 1)) {
204  value += image[AD(x,y+1,w)+BLUE];
205  div++;
206  }
207  if (y) {
208  value += image[AD(x,y-1,w)+BLUE];
209  div++;
210  }
211  image[AD(x,y,w)+BLUE] = value / div;
212 
213  } else if ( bayer == p2 ) {
214 
215  /* green. blue lr, red tb */
216  div = value = 0;
217 
218  if (x < (w - 1)) {
219  value += image[AD(x+1,y,w)+BLUE];
220  div++;
221  }
222  if (x) {
223  value += image[AD(x-1,y,w)+BLUE];
224  div++;
225  }
226  image[AD(x,y,w)+BLUE] = value / div;
227 
228  div = value = 0;
229  if (y < (h - 1)) {
230  value += image[AD(x,y+1,w)+RED];
231  div++;
232  }
233  if (y) {
234  value += image[AD(x,y-1,w)+RED];
235  div++;
236  }
237  image[AD(x,y,w)+RED] = value / div;
238 
239  } else {
240 
241  /* blue. green lrtb, red diagonals */
242  image[AD(x,y,w)+GREEN] =
243  gp_bayer_accrue (image, w, h, x-1, y, x+1, y, x, y-1, x, y+1, GREEN) ;
244 
245  image[AD(x,y,w)+RED] =
246  gp_bayer_accrue (image, w, h, x+1, y+1, x-1, y-1, x-1, y+1, x+1, y-1, RED) ;
247  }
248  }
249 
250  return (GP_OK);
251 }
262 static int
263 gp_bayer_accrue (unsigned char *image, int w, int h, int x0, int y0,
264  int x1, int y1, int x2, int y2, int x3, int y3, int colour)
265 { int x [4] ;
266  int y [4] ;
267  int value [4] ;
268  int above [4] ;
269  int counter ;
270  int sum_of_values;
271  int average ;
272  int i ;
273  x[0] = x0 ; x[1] = x1 ; x[2] = x2 ; x[3] = x3 ;
274  y[0] = y0 ; y[1] = y1 ; y[2] = y2 ; y[3] = y3 ;
275 
276  /* special treatment for green */
277  counter = sum_of_values = 0 ;
278  if(colour == GREEN)
279  {
280  /* We need to make sure that horizontal or vertical lines
281  * become horizontal and vertical lines even in this
282  * interpolation procedure. Therefore, we determine whether
283  * we might have such a line structure.
284  */
285 
286  for (i = 0 ; i < 4 ; i++)
287  { if ((x[i] >= 0) && (x[i] < w) && (y[i] >= 0) && (y[i] < h))
288  {
289  value [i] = image[AD(x[i],y[i],w) + colour] ;
290  counter++;
291  }
292  else
293  {
294  value [i] = -1 ;
295  }
296  }
297  if(counter == 4)
298  {
299  /* It is assumed that x0,y0 and x1,y1 are on a
300  * horizontal line and
301  * x2,y2 and x3,y3 are on a vertical line
302  */
303  int hdiff ;
304  int vdiff ;
305  hdiff = value [1] - value [0] ;
306  hdiff *= hdiff ; /* Make value positive by squaring */
307  vdiff = value [3] - value [2] ;
308  vdiff *= vdiff ; /* Make value positive by squaring */
309  if(hdiff > 2*vdiff)
310  {
311  /* We might have a vertical structure here */
312  return (value [3] + value [2])/2 ;
313  }
314  if(vdiff > 2*hdiff)
315  {
316  /* we might have a horizontal structure here */
317  return (value [1] + value [0])/2 ;
318  }
319  /* else we proceed as with blue and red */
320  }
321  /* if we do not have four points then we proceed as we do for
322  * blue and red */
323  }
324 
325  /* for blue and red */
326  counter = sum_of_values = 0 ;
327  for (i = 0 ; i < 4 ; i++)
328  { if ((x[i] >= 0) && (x[i] < w) && (y[i] >= 0) && (y[i] < h))
329  { value [i] = image[AD(x[i],y[i],w) + colour] ;
330  sum_of_values += value [i] ;
331  counter++ ;
332  }
333  }
334  average = sum_of_values / counter ;
335  if (counter < 4) return average ;
336  /* Less than four surrounding - just take average */
337  counter = 0 ;
338  for (i = 0 ; i < 4 ; i++)
339  { above[i] = value[i] > average ;
340  if (above[i]) counter++ ;
341  }
342  /* Note: counter == 0 indicates all values the same */
343  if ((counter == 2) || (counter == 0)) return average ;
344  sum_of_values = 0 ;
345  for (i = 0 ; i < 4 ; i++)
346  { if ((counter == 3) == above[i])
347  { sum_of_values += value[i] ; }
348  }
349  return sum_of_values / 3 ;
350 }
351 
370 int
371 gp_bayer_decode (unsigned char *input, int w, int h, unsigned char *output,
372  BayerTile tile)
373 {
374  gp_bayer_expand (input, w, h, output, tile);
375  gp_bayer_interpolate (output, w, h, tile);
376 
377  return (GP_OK);
378 }
int gp_bayer_interpolate(unsigned char *image, int w, int h, BayerTile tile)
Interpolate a expanded bayer array into an RGB image.
Definition: bayer.c:147
#define BLUE
Definition: bayer.c:49
#define AD(x, y, w)
Definition: bayer.c:130
static const int tile_colours[8][4]
Definition: bayer.c:37
#define RED
Definition: bayer.c:47
static int gp_bayer_accrue(unsigned char *image, int w, int h, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int colour)
interpolate one pixel from a bayer 2x2 raster
Definition: bayer.c:263
#define GREEN
Definition: bayer.c:48
int gp_bayer_expand(unsigned char *input, int w, int h, unsigned char *output, BayerTile tile)
Expand a bayer raster style image to a RGB raster.
Definition: bayer.c:75
int gp_bayer_decode(unsigned char *input, int w, int h, unsigned char *output, BayerTile tile)
Convert a bayer raster style image to a RGB raster.
Definition: bayer.c:371
BayerTile
how the bayer CCD array is laid out
Definition: bayer.h:32
@ BAYER_TILE_GBRG_INTERLACED
scanline order: G1,B1,G2,B2,...,R1,G1,R2,G2,...
Definition: bayer.h:40
@ BAYER_TILE_GBRG
raster is RG,GB
Definition: bayer.h:36
@ BAYER_TILE_RGGB_INTERLACED
scanline order: R1,G1,R2,G2,...,G1,B1,G2,B2,...
Definition: bayer.h:37
@ BAYER_TILE_BGGR_INTERLACED
scanline order: B1,G1,R2,G2,...,G1,R1,G2,R2,...
Definition: bayer.h:39
@ BAYER_TILE_BGGR
raster is BG,GR
Definition: bayer.h:35
@ BAYER_TILE_RGGB
raster is RG,GN
Definition: bayer.h:33
@ BAYER_TILE_GRBG
raster is GR,BG
Definition: bayer.h:34
@ BAYER_TILE_GRBG_INTERLACED
scanline order: G1,R1,R2,G2,...,B1,G1,B2,G2,...
Definition: bayer.h:38
void gp_log(GPLogLevel level, const char *domain, const char *format,...)
Log a debug or error message.
@ GP_LOG_DEBUG
Log message is an debug information.
#define GP_OK
Everything is OK.
#define GP_ERROR
Generic Error.