Fawkes API  Fawkes Development Version
bayer.cpp
1 
2 /***************************************************************************
3  * bayer.cpp - methods to convert bayer mosaic images to other formats
4  *
5  * Generated: Fri Aug 11 00:03:32 2006
6  * Copyright 2005-2006 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <fvutils/color/bayer.h>
25 #include <fvutils/color/colorspaces.h>
26 #include <fvutils/color/rgbyuv.h>
27 #include <fvutils/color/yuv.h>
28 
29 namespace firevision {
30 
31 /* The basic information has been taken from
32  * http://www-ise.stanford.edu/~tingchen/
33  */
34 
35 #define assign(y, u, v, y1, u1, v1, y2, u2, v2) \
36  { \
37  *y++ = y1; \
38  *y++ = y2; \
39  *u++ = ((u1 + u2) >> 1); \
40  *v++ = ((v1 + v2) >> 1); \
41  }
42 
43 void
44 bayerGBRG_to_yuv422planar_nearest_neighbour(const unsigned char *bayer,
45  unsigned char * yuv,
46  unsigned int width,
47  unsigned int height)
48 {
49  unsigned char * y = yuv;
50  unsigned char * u = YUV422_PLANAR_U_PLANE(yuv, width, height);
51  unsigned char * v = YUV422_PLANAR_V_PLANE(yuv, width, height);
52  const unsigned char *b = bayer;
53 
54  int y1, u1, v1, y2, u2, v2;
55  int t1, t2;
56 
57  for (unsigned int h = 0; h < height; h += 2) {
58  // g b ... line
59  for (unsigned int w = 0; w < width; w += 2) {
60  t1 = b[width];
61  t2 = b[1];
62  RGB2YUV(t1, *b, t2, y1, u1, v1);
63  ++b;
64 
65  t1 = b[width - 1];
66  t2 = b[-1];
67  RGB2YUV(t1, t2, *b, y2, u2, v2);
68  ++b;
69 
70  assign(y, u, v, y1, u1, v1, y2, u2, v2);
71  }
72 
73  // r g ... line
74  for (unsigned int w = 0; w < width; w += 2) {
75  t1 = b[1];
76  t2 = b[-width + 1];
77  RGB2YUV(*b, t1, t2, y1, u1, v1);
78  ++b;
79 
80  t1 = b[-1];
81  t2 = b[-width];
82  RGB2YUV(t1, *b, t2, y2, u2, v2);
83  ++b;
84 
85  assign(y, u, v, y1, u1, v1, y2, u2, v2);
86  }
87  }
88 }
89 
90 void
91 bayerGBRG_to_yuv422planar_bilinear(const unsigned char *bayer,
92  unsigned char * yuv,
93  unsigned int width,
94  unsigned int height)
95 {
96  unsigned char * y = yuv;
97  unsigned char * u = YUV422_PLANAR_U_PLANE(yuv, width, height);
98  unsigned char * v = YUV422_PLANAR_V_PLANE(yuv, width, height);
99  const unsigned char *bf = bayer;
100 
101  int y1, u1, v1, y2, u2, v2;
102  int r, g, b;
103 
104  // first line is special
105  // g b ... line
106  // not full data in first columns
107  RGB2YUV(bf[width], *bf, bf[1], y1, u1, v1);
108  ++bf;
109 
110  r = (bf[width - 1] + bf[width + 1]) >> 1;
111  // correct:
112  // g = (bf[-1] + bf[width] + bf[1]) / 3;
113  // faster:
114  g = (bf[-1] + bf[1]) >> 1;
115  RGB2YUV(r, g, *bf, y2, u2, v2);
116  ++bf;
117 
118  assign(y, u, v, y1, u1, v1, y2, u2, v2);
119 
120  // rest of first line
121  for (unsigned int w = 2; w < width - 2; w += 2) {
122  b = (bf[-1] + bf[1]) >> 1;
123  RGB2YUV(bf[width], *bf, b, y1, u1, v1);
124  ++bf;
125 
126  r = (bf[width - 1] + bf[width + 1]) >> 1;
127  // correct:
128  // g = (bf[-1] + bf[width] + bf[1]) / 3;
129  // faster:
130  g = (bf[-1] + bf[1]) >> 1;
131  RGB2YUV(r, g, *bf, y2, u2, v2);
132  ++bf;
133 
134  assign(y, u, v, y1, u1, v1, y2, u2, v2);
135  }
136 
137  // not full data in last columns
138  b = (bf[-1] + bf[1]) >> 1;
139  RGB2YUV(bf[width], *bf, b, y1, u1, v1);
140  ++bf;
141 
142  g = (bf[-1] + bf[width]) >> 1;
143  RGB2YUV(bf[width - 1], g, *bf, y2, u2, v2);
144  ++bf;
145 
146  assign(y, u, v, y1, u1, v1, y2, u2, v2);
147 
148  for (unsigned int h = 1; h < height - 1; h += 2) {
149  // r g ... line
150  // correct: g = (bf[-width] + bf[1] + bf[width]) / 3;
151  // faster:
152  g = (bf[-width] + bf[1]) >> 1;
153  b = (bf[width - 1] + bf[width + 1]) >> 1;
154  RGB2YUV(*bf, g, b, y1, u1, v1);
155  ++bf;
156 
157  r = (bf[-1] + bf[1]) >> 1;
158  b = (bf[-width] + bf[width]) >> 1;
159  RGB2YUV(r, *bf, b, y2, u2, v2);
160  ++bf;
161 
162  assign(y, u, v, y1, u1, v1, y2, u2, v2);
163 
164  for (unsigned int w = 2; w < width - 2; w += 2) {
165  g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
166  b = (bf[-width - 1] + bf[-width + 1] + bf[width - 1] + bf[width + 1]) >> 2;
167  RGB2YUV(*bf, g, b, y1, u1, v1);
168  ++bf;
169 
170  r = (bf[-1] + bf[1]) >> 1;
171  b = (bf[-width] + bf[width]) >> 1;
172  RGB2YUV(r, *bf, b, y2, u2, v2);
173  ++bf;
174 
175  assign(y, u, v, y1, u1, v1, y2, u2, v2);
176  }
177 
178  g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
179  b = (bf[-width - 1] + bf[-width + 1] + bf[width - 1] + bf[width + 1]) >> 2;
180  RGB2YUV(*bf, g, b, y1, u1, v1);
181  ++bf;
182 
183  b = (bf[-width] + bf[width]) >> 1;
184  RGB2YUV(bf[-1], *bf, g, y2, u2, v2);
185  ++bf;
186 
187  assign(y, u, v, y1, u1, v1, y2, u2, v2);
188 
189  // g b ... line
190  r = (bf[width] + bf[-width]) >> 1;
191  RGB2YUV(r, *bf, bf[1], y1, u1, v1);
192  ++bf;
193 
194  r = (bf[-width - 1] + bf[-width + 1] + bf[width - 1] + bf[width + 1]) >> 2;
195  g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
196  RGB2YUV(r, g, *bf, y2, u2, v2);
197  ++bf;
198 
199  assign(y, u, v, y1, u1, v1, y2, u2, v2);
200 
201  for (unsigned int w = 2; w < width - 2; w += 2) {
202  r = (bf[width] + bf[-width]) >> 1;
203  b = (bf[-1] + bf[1]) >> 1;
204  RGB2YUV(r, *bf, b, y1, u1, v1);
205  ++bf;
206 
207  r = (bf[-width - 1] + bf[-width + 1] + bf[width - 1] + bf[width + 1]) >> 2;
208  g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
209  RGB2YUV(r, g, *bf, y2, u2, v2);
210  ++bf;
211 
212  assign(y, u, v, y1, u1, v1, y2, u2, v2);
213  }
214 
215  r = (bf[width] + bf[-width]) >> 1;
216  b = (bf[-1] + bf[1]) >> 1;
217  RGB2YUV(r, *bf, b, y1, u1, v1);
218  ++bf;
219 
220  r = (bf[-width - 1] + bf[width - 1]) >> 1;
221  // correct: g = (bf[-width] + bf[width] + bf[-1]) / 3;
222  // faster:
223  g = (bf[-width] + bf[-1]) >> 1;
224  RGB2YUV(r, g, *bf, y2, u2, v2);
225  ++bf;
226 
227  assign(y, u, v, y1, u1, v1, y2, u2, v2);
228  }
229 
230  // last r g ... line
231  // correct: g = (bf[-width] + bf[1] + bf[width]) / 3;
232  // faster:
233  g = (bf[-width] + bf[1]) >> 1;
234  b = bf[-width + 1];
235  RGB2YUV(*bf, g, b, y1, u1, v1);
236  ++bf;
237 
238  r = (bf[-1] + bf[1]) >> 1;
239  b = bf[-width];
240  RGB2YUV(r, g, *bf, y2, u2, v2);
241  ++bf;
242 
243  assign(y, u, v, y1, u1, v1, y2, u2, v2);
244 
245  for (unsigned int w = 2; w < width - 2; w += 2) {
246  // correct: g = (bf[-width] + bf[1] + bf[-1]) / 3
247  // faster:
248  g = (bf[-width] + bf[-1]) >> 1;
249  b = (bf[-width - 1] + bf[-width + 1]) >> 1;
250  RGB2YUV(*bf, g, b, y1, u1, v1);
251  ++bf;
252 
253  r = (bf[-1] + bf[1]) >> 1;
254  b = bf[-width];
255  RGB2YUV(r, *bf, b, y2, u2, v2);
256  ++bf;
257 
258  assign(y, u, v, y1, u1, v1, y2, u2, v2);
259  }
260 
261  // correct: g = (bf[-width] + bf[1] + bf[-1]) / 3;
262  // faster:
263  g = (bf[-width] + bf[-1]) >> 1;
264  b = (bf[-width - 1] + bf[-width + 1]) >> 1;
265  RGB2YUV(*bf, g, b, y1, u1, v1);
266  ++bf;
267 
268  b = bf[-width];
269  RGB2YUV(bf[-1], *bf, b, y2, u2, v2);
270  ++bf;
271 
272  assign(y, u, v, y1, u1, v1, y2, u2, v2);
273 }
274 
275 void
276 bayerGBRG_to_yuv422planar_bilinear2(const unsigned char *bayer,
277  unsigned char * yuv,
278  unsigned int width,
279  unsigned int height)
280 {
281  unsigned char * y = yuv;
282  unsigned char * u = YUV422_PLANAR_U_PLANE(yuv, width, height);
283  unsigned char * v = YUV422_PLANAR_V_PLANE(yuv, width, height);
284  const unsigned char *bf = bayer;
285 
286  int y1, u1, v1, y2, u2, v2;
287  int r, g, b;
288 
289  // ignore first g b ... line
290  bf += width;
291  y += width;
292  u += width >> 1;
293  v += width >> 1;
294 
295  for (unsigned int h = 1; h < height - 1; h += 2) {
296  // r g ... line
297  // ignore first two columns
298  ++bf;
299  ++bf;
300  ++y;
301  ++y;
302  ++u;
303  ++v;
304 
305  for (unsigned int w = 2; w < width - 2; w += 2) {
306  g = (bf[1] + bf[-1]) >> 1;
307  b = (bf[width - 1] + bf[width + 1]) >> 1;
308  RGB2YUV(*bf, g, b, y1, u1, v1);
309  ++bf;
310 
311  r = (bf[-1] + bf[1]) >> 1;
312  b = (bf[-width] + bf[width]) >> 1;
313  RGB2YUV(r, *bf, b, y2, u2, v2);
314  ++bf;
315 
316  assign(y, u, v, y1, u1, v1, y2, u2, v2);
317  }
318 
319  // ignore last two columns
320  ++bf;
321  ++bf;
322  ++y;
323  ++y;
324  ++u;
325  ++v;
326 
327  // g b ... line
328  // ignore first two columns
329  ++bf;
330  ++bf;
331  ++y;
332  ++y;
333  ++u;
334  ++v;
335 
336  for (unsigned int w = 2; w < width - 2; w += 2) {
337  r = (bf[width] + bf[-width]) >> 1;
338  b = (bf[-1] + bf[1]) >> 1;
339  RGB2YUV(r, *bf, b, y1, u1, v1);
340  ++bf;
341 
342  r = (bf[width - 1] + bf[width + 1]) >> 1;
343  g = (bf[1] + bf[width]) >> 1;
344  RGB2YUV(r, g, *bf, y2, u2, v2);
345  ++bf;
346 
347  assign(y, u, v, y1, u1, v1, y2, u2, v2);
348  }
349 
350  // ignore last two columns
351  ++bf;
352  ++bf;
353  ++y;
354  ++y;
355  ++u;
356  ++v;
357  }
358 
359  // ignore last r g ... line
360 }
361 
362 /* Not faster in benchmarks
363 void
364 bayerGBRG_to_yuv422planar_bilinear2(const unsigned char *bayer, unsigned char *yuv,
365  unsigned int width, unsigned int height)
366 {
367  unsigned char *y = yuv;
368  unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height);
369  unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height);
370  unsigned char *bf = bayer;
371 
372  int y1, u1, v1, y2, u2, v2;
373  int r, g, b;
374 
375  // first line is special
376  // g b ... line
377  // not full data in first columns
378  RGB2YUV(*(bf + width), *bf, *(bf + 1), y1, u1, v1);
379  ++bf;
380 
381  r = (*(bf + width - 1) + *(bf + width + 1)) >> 1;
382  // correct:
383  // g = (*(bf - 1) + *(bf + width) + *(bf + 1)) / 3;
384  // faster:
385  g = (*(bf -1) + *(bf +1)) >> 1;
386  RGB2YUV(r, g, *bf, y2, u2, v2);
387  ++bf;
388 
389  assign(y, u, v, y1, u1, v1, y2, u2, v2);
390 
391  // rest of first line
392  for (unsigned int w = 2; w < width - 2; w += 2) {
393  b = (*(bf - 1) + *(bf + 1)) >> 1;
394  RGB2YUV(*(bf + width), *bf, b, y1, u1, v1);
395  ++bf;
396 
397  r = (*(bf + width - 1) + *(bf + width + 1)) >> 1;
398  // correct:
399  // g = (*(bf - 1) + *(bf + width) + *(bf + 1)) / 3;
400  // faster:
401  g = (*(bf - 1) + *(bf + 1)) >> 1;
402  RGB2YUV(r, g, *bf, y2, u2, v2);
403  ++bf;
404 
405  assign(y, u, v, y1, u1, v1, y2, u2, v2);
406  }
407 
408  // not full data in last columns
409  b = (*(bf - 1) + *(bf + 1)) >> 1;
410  RGB2YUV(*(bf + width), *bf, b, y1, u1, v1);
411  ++bf;
412 
413  g = (*(bf - 1) + *(bf + width)) >> 1;
414  RGB2YUV(*(bf + width - 1), g, *bf, y2, u2, v2);
415  ++bf;
416 
417  assign(y, u, v, y1, u1, v1, y2, u2, v2);
418 
419  for ( unsigned int h = 1; h < height - 1; h += 2) {
420 
421  // r g ... line
422  // correct: g = (*(bf - width) + *(bf + 1) + *(bf + width)) / 3;
423  // faster:
424  g = (*(bf - width) + *(bf + 1)) >> 1;
425  b = (*(bf + width - 1) + *(bf + width + 1)) >> 1;
426  RGB2YUV(*bf, g, b, y1, u1, v1);
427  ++bf;
428 
429  r = (*(bf - 1) + *(bf + 1)) >> 1;
430  b = (*(bf - width) + *(bf + width)) >> 1;
431  RGB2YUV(r, *bf, g, y2, u2, v2);
432  ++bf;
433 
434  assign(y, u, v, y1, u1, v1, y2, u2, v2);
435 
436  for (unsigned int w = 2; w < width - 2; w += 2) {
437  g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
438  b = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
439  RGB2YUV(*bf, g, b, y1, u1, v1);
440  ++bf;
441 
442  r = (*(bf - 1) + *(bf + 1)) >> 1;
443  b = (*(bf - width) + *(bf + width)) >> 1;
444  RGB2YUV(r, *bf, b, y2, u2, v2);
445  ++bf;
446 
447  assign(y, u, v, y1, u1, v1, y2, u2, v2);
448  }
449 
450  g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
451  b = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
452  RGB2YUV(*bf, g, b, y1, u1, v1);
453  ++bf;
454 
455  b = (*(bf - width) + *(bf + width)) >> 1;
456  RGB2YUV(*(bf - 1), *bf, g, y2, u2, v2);
457  ++bf;
458 
459  assign(y, u, v, y1, u1, v1, y2, u2, v2);
460 
461 
462 
463  // g b ... line
464  r = (*(bf + width) + *(bf - width)) >> 1;
465  RGB2YUV(r, *bf, *(bf + 1), y1, u1, v1);
466  ++bf;
467 
468  r = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
469  g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
470  RGB2YUV(r, g, *bf, y2, u2, v2);
471  ++bf;
472 
473  assign(y, u, v, y1, u1, v1, y2, u2, v2);
474 
475  for (unsigned int w = 2; w < width - 2; w += 2) {
476  r = (*(bf + width) + *(bf - width)) >> 1;
477  b = (*(bf - 1) + *(bf + 1)) >> 1;
478  RGB2YUV(r, *bf, b, y1, u1, v1);
479  ++bf;
480 
481  r = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
482  g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
483  RGB2YUV(r, g, *bf, y2, u2, v2);
484  ++bf;
485 
486  assign(y, u, v, y1, u1, v1, y2, u2, v2);
487  }
488 
489  r = (*(bf + width) + *(bf - width)) >> 1;
490  b = (*(bf - 1) + *(bf + 1)) >> 1;
491  RGB2YUV(r, *bf, b, y1, u1, v1);
492  ++bf;
493 
494  r = (*(bf - width - 1) + *(bf + width - 1)) >> 1;
495  // correct: g = (*(bf - width) + *(bf + width) + *(bf - 1)) / 3;
496  // faster:
497  g = (*(bf - width) + *(bf - 1)) >> 1;
498  RGB2YUV(r, g, *bf, y2, u2, v2);
499  ++bf;
500 
501  assign(y, u, v, y1, u1, v1, y2, u2, v2);
502  }
503 
504  // last r g ... line
505  // correct: g = (*(bf - width) + *(bf + 1) + *(bf + width)) / 3;
506  // faster:
507  g = (*(bf - width) + *(bf + 1)) >> 1;
508  b = *(bf - width + 1);
509  RGB2YUV(*bf, g, b, y1, u1, v1);
510  ++bf;
511 
512  r = (*(bf - 1) + *(bf + 1)) >> 1;
513  b = *(bf - width);
514  RGB2YUV(r, g, *bf, y2, u2, v2);
515  ++bf;
516 
517  assign(y, u, v, y1, u1, v1, y2, u2, v2);
518 
519  for (unsigned int w = 2; w < width - 2; w += 2) {
520  // correct: g = (*(bf - width) + *(bf + 1) + *(bf - 1)) / 3
521  // faster:
522  g = (*(bf - width) + *(bf - 1)) >> 1;
523  b = (*(bf - width - 1) + *(bf - width + 1)) >> 1;
524  RGB2YUV(*bf, g, b, y1, u1, v1);
525  ++bf;
526 
527  r = (*(bf - 1) + *(bf + 1)) >> 1;
528  b = *(bf - width);
529  RGB2YUV(r, *bf, b, y2, u2, v2);
530  ++bf;
531 
532  assign(y, u, v, y1, u1, v1, y2, u2, v2);
533  }
534 
535  // correct: g = (*(bf - width) + *(bf + 1) + *(bf - 1)) / 3;
536  // faster:
537  g = (*(bf - width) + *(bf - 1)) >> 1;
538  b = (*(bf - width - 1) + *(bf - width + 1)) >> 1;
539  RGB2YUV(*bf, g, b, y1, u1, v1);
540  ++bf;
541 
542  b = *(bf - width);
543  RGB2YUV(*(bf - 1), *bf, b, y2, u2, v2);
544  ++bf;
545 
546  assign(y, u, v, y1, u1, v1, y2, u2, v2);
547 
548 }
549 */
550 
551 void
552 bayerGRBG_to_yuv422planar_nearest_neighbour(const unsigned char *bayer,
553  unsigned char * yuv,
554  unsigned int width,
555  unsigned int height)
556 {
557  unsigned char * y = yuv;
558  unsigned char * u = YUV422_PLANAR_U_PLANE(yuv, width, height);
559  unsigned char * v = YUV422_PLANAR_V_PLANE(yuv, width, height);
560  const unsigned char *b = bayer;
561 
562  int y1, u1, v1, y2, u2, v2;
563 
564  for (unsigned int h = 0; h < height; h += 2) {
565  // g r ... line
566  for (unsigned int w = 0; w < width; w += 2) {
567  RGB2YUV(b[1], b[width], *b, y1, u1, v1);
568  ++b;
569 
570  RGB2YUV(*b, b[-1], b[width - 1], y2, u2, v2);
571  ++b;
572 
573  assign(y, u, v, y1, u1, v1, y2, u2, v2);
574  }
575 
576  // b g ... line
577  for (unsigned int w = 0; w < width; w += 2) {
578  RGB2YUV(*(b - width + 1), b[1], *b, y1, u1, v1);
579  ++b;
580 
581  RGB2YUV(*(b - width), *b, b[-1], y2, u2, v2);
582  ++b;
583 
584  assign(y, u, v, y1, u1, v1, y2, u2, v2);
585  }
586  }
587 }
588 
589 void
590 bayerRGGB_to_yuv422planar_nearest_neighbour(const unsigned char *bayer,
591  unsigned char * yuv,
592  unsigned int width,
593  unsigned int height)
594 {
595  unsigned char * y = yuv;
596  unsigned char * u = YUV422_PLANAR_U_PLANE(yuv, width, height);
597  unsigned char * v = YUV422_PLANAR_V_PLANE(yuv, width, height);
598  const unsigned char *b = bayer;
599 
600  int y1, u1, v1, y2, u2, v2;
601 
602  for (unsigned int h = 0; h < height; h += 2) {
603  // r g ... line
604  for (unsigned int w = 0; w < width; w += 2) {
605  RGB2YUV(*b, b[1], b[width + 1], y1, u1, v1);
606  ++b;
607 
608  RGB2YUV(b[-1], *b, b[width], y2, u2, v2);
609  ++b;
610 
611  assign(y, u, v, y1, u1, v1, y2, u2, v2);
612  }
613 
614  // g b ... line
615  for (unsigned int w = 0; w < width; w += 2) {
616  RGB2YUV(*(b - width), *b, b[1], y1, u1, v1);
617  ++b;
618 
619  RGB2YUV(*(b - width - 1), b[-1], *b, y2, u2, v2);
620  ++b;
621 
622  assign(y, u, v, y1, u1, v1, y2, u2, v2);
623  }
624  }
625 }
626 
627 void
628 bayerGRBG_to_yuv422planar_bilinear(const unsigned char *bayer,
629  unsigned char * yuv,
630  unsigned int width,
631  unsigned int height)
632 {
633  unsigned char * y = yuv;
634  unsigned char * u = YUV422_PLANAR_U_PLANE(yuv, width, height);
635  unsigned char * v = YUV422_PLANAR_V_PLANE(yuv, width, height);
636  const unsigned char *bf = bayer;
637 
638  int y1, u1, v1, y2, u2, v2;
639  int r, g, b;
640 
641  // first line is special
642  // g r ... line
643  // not full data in first columns
644  RGB2YUV(bf[1], *bf, bf[width], y1, u1, v1);
645  ++bf;
646 
647  b = (bf[width - 1] + bf[width + 1]) >> 1;
648  // correct:
649  // g = (bf[-1] + bf[width] + bf[1]) / 3;
650  // faster:
651  g = (bf[-1] + bf[1]) >> 1;
652  RGB2YUV(*bf, g, b, y2, u2, v2);
653  ++bf;
654 
655  assign(y, u, v, y1, u1, v1, y2, u2, v2);
656 
657  // rest of first line
658  for (unsigned int w = 2; w < width - 2; w += 2) {
659  r = (bf[-1] + bf[1]) >> 1;
660  RGB2YUV(r, *bf, bf[width], y1, u1, v1);
661  ++bf;
662 
663  b = (bf[width - 1] + bf[width + 1]) >> 1;
664  // correct:
665  // g = (bf[-1] + bf[width] + bf[1]) / 3;
666  // faster:
667  g = (bf[-1] + bf[1]) >> 1;
668  RGB2YUV(*bf, g, b, y2, u2, v2);
669  ++bf;
670 
671  assign(y, u, v, y1, u1, v1, y2, u2, v2);
672  }
673 
674  // not full data in last columns
675  r = (bf[-1] + bf[1]) >> 1;
676  RGB2YUV(r, *bf, bf[width], y1, u1, v1);
677  ++bf;
678 
679  g = (bf[-1] + bf[width]) >> 1;
680  RGB2YUV(*bf, g, bf[width - 1], y2, u2, v2);
681  ++bf;
682 
683  assign(y, u, v, y1, u1, v1, y2, u2, v2);
684 
685  for (unsigned int h = 1; h < height - 1; h += 2) {
686  // b g ... line
687  // correct: g = (*(bf-width) + bf[1] + bf[width]) / 3;
688  // faster:
689  g = (*(bf - width) + bf[1]) >> 1;
690  r = (*(bf - width + 1) + bf[width + 1]) >> 1;
691  RGB2YUV(r, g, *bf, y1, u1, v1);
692  ++bf;
693 
694  b = (bf[-1] + bf[1]) >> 1;
695  r = (*(bf - width) + bf[width]) >> 1;
696  RGB2YUV(r, *bf, g, y2, u2, v2);
697  ++bf;
698 
699  assign(y, u, v, y1, u1, v1, y2, u2, v2);
700 
701  for (unsigned int w = 2; w < width - 2; w += 2) {
702  g = (*(bf - width) + bf[1] + bf[width] + bf[-1]) >> 2;
703  r = (*(bf - width - 1) + *(bf - width + 1) + bf[width - 1] + bf[width + 1]) >> 2;
704  RGB2YUV(r, g, *bf, y1, u1, v1);
705  ++bf;
706 
707  b = (bf[-1] + bf[1]) >> 1;
708  r = (*(bf - width) + bf[width]) >> 1;
709  RGB2YUV(r, *bf, b, y2, u2, v2);
710  ++bf;
711 
712  assign(y, u, v, y1, u1, v1, y2, u2, v2);
713  }
714 
715  g = (*(bf - width) + bf[1] + bf[width] + bf[-1]) >> 2;
716  r = (*(bf - width - 1) + *(bf - width + 1) + bf[width - 1] + bf[width + 1]) >> 2;
717  RGB2YUV(r, g, *bf, y1, u1, v1);
718  ++bf;
719 
720  r = (*(bf - width) + bf[width]) >> 1;
721  RGB2YUV(r, *bf, bf[-1], y2, u2, v2);
722  ++bf;
723 
724  assign(y, u, v, y1, u1, v1, y2, u2, v2);
725 
726  // g r ... line
727  b = (bf[width] + *(bf - width)) >> 1;
728  RGB2YUV(bf[1], *bf, b, y1, u1, v1);
729  ++bf;
730 
731  b = (*(bf - width - 1) + *(bf - width + 1) + bf[width - 1] + bf[width + 1]) >> 2;
732  g = (*(bf - width) + bf[1] + bf[width] + bf[-1]) >> 2;
733  RGB2YUV(*bf, g, b, y2, u2, v2);
734  ++bf;
735 
736  assign(y, u, v, y1, u1, v1, y2, u2, v2);
737 
738  for (unsigned int w = 2; w < width - 2; w += 2) {
739  b = (bf[width] + *(bf - width)) >> 1;
740  r = (bf[-1] + bf[1]) >> 1;
741  RGB2YUV(r, *bf, b, y1, u1, v1);
742  ++bf;
743 
744  b = (*(bf - width - 1) + *(bf - width + 1) + bf[width - 1] + bf[width + 1]) >> 2;
745  g = (*(bf - width) + bf[1] + bf[width] + bf[-1]) >> 2;
746  RGB2YUV(*bf, g, b, y2, u2, v2);
747  ++bf;
748 
749  assign(y, u, v, y1, u1, v1, y2, u2, v2);
750  }
751 
752  b = (bf[width] + *(bf - width)) >> 1;
753  r = (bf[-1] + bf[1]) >> 1;
754  RGB2YUV(r, *bf, b, y1, u1, v1);
755  ++bf;
756 
757  b = (*(bf - width - 1) + bf[width - 1]) >> 1;
758  // correct: g = (*(bf-width) + bf[width] + bf[-1]) / 3;
759  // faster:
760  g = (*(bf - width) + bf[-1]) >> 1;
761  RGB2YUV(*bf, g, r, y2, u2, v2);
762  ++bf;
763 
764  assign(y, u, v, y1, u1, v1, y2, u2, v2);
765  }
766 
767  // last b g ... line
768  // correct: g = (*(bf-width) + bf[1] + bf[width]) / 3;
769  // faster:
770  g = (*(bf - width) + bf[1]) >> 1;
771  r = *(bf - width + 1);
772  RGB2YUV(r, g, *bf, y1, u1, v1);
773  ++bf;
774 
775  b = (bf[-1] + bf[1]) >> 1;
776  r = *(bf - width);
777  RGB2YUV(r, *bf, b, y2, u2, v2);
778  ++bf;
779 
780  assign(y, u, v, y1, u1, v1, y2, u2, v2);
781 
782  for (unsigned int w = 2; w < width - 2; w += 2) {
783  // correct: g = (*(bf-width) + bf[1] + bf[-1]) / 3
784  // faster:
785  g = (*(bf - width) + bf[-1]) >> 1;
786  r = (*(bf - width - 1) + *(bf - width + 1)) >> 1;
787  RGB2YUV(r, g, *bf, y1, u1, v1);
788  ++bf;
789 
790  b = (bf[-1] + bf[1]) >> 1;
791  r = *(bf - width);
792  RGB2YUV(r, *bf, b, y2, u2, v2);
793  ++bf;
794 
795  assign(y, u, v, y1, u1, v1, y2, u2, v2);
796  }
797 
798  // correct: g = (*(bf-width) + bf[1] + bf[-1]) / 3;
799  // faster:
800  g = (*(bf - width) + bf[-1]) >> 1;
801  r = (*(bf - width - 1) + *(bf - width + 1)) >> 1;
802  RGB2YUV(r, g, *bf, y1, u1, v1);
803  ++bf;
804 
805  r = *(bf - width);
806  RGB2YUV(r, *bf, bf[-1], y2, u2, v2);
807  ++bf;
808 
809  assign(y, u, v, y1, u1, v1, y2, u2, v2);
810 }
811 
812 void
813 bayerGRBG_to_rgb_nearest_neighbour(const unsigned char *bayer,
814  unsigned char * rgb,
815  unsigned int width,
816  unsigned int height)
817 {
818  for (unsigned int h = 0; h < height; h += 2) {
819  // g r ... line
820  for (unsigned int w = 0; w < width; w += 2) {
821  *rgb++ = bayer[1];
822  *rgb++ = bayer[width];
823  *rgb++ = *bayer;
824  ++bayer;
825 
826  *rgb++ = *bayer;
827  *rgb++ = bayer[-1];
828  *rgb++ = bayer[width - 1];
829  ++bayer;
830  }
831 
832  // b g ... line
833  for (unsigned int w = 0; w < width; w += 2) {
834  *rgb++ = *(bayer - width + 1);
835  *rgb++ = bayer[1];
836  *rgb++ = *bayer;
837  ++bayer;
838 
839  *rgb++ = *(bayer - width);
840  *rgb++ = *bayer;
841  *rgb++ = bayer[-1];
842  ++bayer;
843  }
844  }
845 }
846 
847 void
848 bayerGRBG_to_rgb_bilinear(const unsigned char *bayer,
849  unsigned char * rgb,
850  unsigned int width,
851  unsigned int height)
852 {
853  // first line is special
854  // g r ... line
855  // not full data in first columns
856  *rgb++ = bayer[1];
857  *rgb++ = *bayer;
858  *rgb++ = bayer[width];
859  ++bayer;
860 
861  // correct:
862  // g = (bayer[-1] + bayer[width] + bayer[1]) / 3;
863  // faster:
864  *rgb++ = *bayer;
865  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
866  *rgb++ = (bayer[width - 1] + bayer[width + 1]) >> 1;
867  ++bayer;
868 
869  // rest of first line
870  for (unsigned int w = 2; w < width - 2; w += 2) {
871  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
872  *rgb++ = *bayer;
873  *rgb++ = bayer[width];
874  ++bayer;
875 
876  // correct:
877  // g = (bayer[-1] + bayer[width] + bayer[1]) / 3;
878  // faster:
879  *rgb++ = *bayer;
880  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
881  *rgb++ = (bayer[width - 1] + bayer[width + 1]) >> 1;
882  ++bayer;
883  }
884 
885  // not full data in last columns
886  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
887  *rgb++ = *bayer;
888  *rgb++ = bayer[width];
889  ++bayer;
890 
891  *rgb++ = *bayer;
892  *rgb++ = (bayer[-1] + bayer[width]) >> 1;
893  *rgb++ = bayer[width - 1];
894  ++bayer;
895 
896  for (unsigned int h = 1; h < height - 1; h += 2) {
897  // b g ... line
898  // correct: g = (*(bayer-width) + bayer[1] + bayer[width]) / 3;
899  // faster:
900  *rgb++ = (*(bayer - width + 1) + bayer[width + 1]) >> 1;
901  *rgb++ = (*(bayer - width) + bayer[1]) >> 1;
902  *rgb++ = *bayer;
903  ++bayer;
904 
905  *rgb++ = (*(bayer - width) + bayer[width]) >> 1;
906  *rgb++ = *bayer;
907  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
908  ++bayer;
909 
910  for (unsigned int w = 2; w < width - 2; w += 2) {
911  *rgb++ =
912  (*(bayer - width - 1) + *(bayer - width + 1) + bayer[width - 1] + bayer[width + 1]) >> 2;
913  *rgb++ = (*(bayer - width) + bayer[1] + bayer[width] + bayer[-1]) >> 2;
914  *rgb++ = *bayer;
915  ++bayer;
916 
917  *rgb++ = (*(bayer - width) + bayer[width]) >> 1;
918  *rgb++ = *bayer;
919  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
920  ++bayer;
921  }
922 
923  *rgb++ =
924  (*(bayer - width - 1) + *(bayer - width + 1) + bayer[width - 1] + bayer[width + 1]) >> 2;
925  *rgb++ = (*(bayer - width) + bayer[1] + bayer[width] + bayer[-1]) >> 2;
926  *rgb++ = *bayer;
927  ++bayer;
928 
929  *rgb++ = (*(bayer - width) + bayer[width]) >> 1;
930  *rgb++ = *bayer;
931  *rgb++ = bayer[-1];
932  ++bayer;
933 
934  // g r ... line
935  *rgb++ = bayer[1];
936  *rgb++ = *bayer;
937  *rgb++ = (bayer[width] + *(bayer - width)) >> 1;
938  ++bayer;
939 
940  *rgb++ = *bayer;
941  *rgb++ = (*(bayer - width) + bayer[1] + bayer[width] + bayer[-1]) >> 2;
942  *rgb++ =
943  (*(bayer - width - 1) + *(bayer - width + 1) + bayer[width - 1] + bayer[width + 1]) >> 2;
944  ++bayer;
945 
946  for (unsigned int w = 2; w < width - 2; w += 2) {
947  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
948  *rgb++ = *bayer;
949  *rgb++ = (bayer[width] + *(bayer - width)) >> 1;
950  ++bayer;
951 
952  *rgb++ = *bayer;
953  *rgb++ = (*(bayer - width) + bayer[1] + bayer[width] + bayer[-1]) >> 2;
954  *rgb++ =
955  (*(bayer - width - 1) + *(bayer - width + 1) + bayer[width - 1] + bayer[width + 1]) >> 2;
956  ++bayer;
957  }
958 
959  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
960  *rgb++ = *bayer;
961  *rgb++ = (bayer[width] + *(bayer - width)) >> 1;
962  ++bayer;
963 
964  // correct: g = (*(bayer-width) + bayer[width] + bayer[-1]) / 3;
965  // faster:
966  *rgb++ = *bayer;
967  *rgb++ = (*(bayer - width) + bayer[-1]) >> 1;
968  *rgb++ = (*(bayer - width - 1) + bayer[width - 1]) >> 1;
969  ++bayer;
970  }
971 
972  // last b g ... line
973  // correct: g = (*(bayer-width) + bayer[1] + bayer[width]) / 3;
974  // faster:
975  *rgb++ = *(bayer - width + 1);
976  *rgb++ = (*(bayer - width) + bayer[1]) >> 1;
977  *rgb++ = *bayer;
978  ++bayer;
979 
980  *rgb++ = *(bayer - width);
981  *rgb++ = *bayer;
982  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
983  ++bayer;
984 
985  for (unsigned int w = 2; w < width - 2; w += 2) {
986  // correct: g = (*(bayer-width) + bayer[1] + bayer[-1]) / 3
987  // faster:
988  *rgb++ = (*(bayer - width - 1) + *(bayer - width + 1)) >> 1;
989  *rgb++ = (*(bayer - width) + bayer[-1]) >> 1;
990  *rgb++ = *bayer;
991  ++bayer;
992 
993  *rgb++ = *(bayer - width);
994  *rgb++ = *bayer;
995  *rgb++ = (bayer[-1] + bayer[1]) >> 1;
996  ++bayer;
997  }
998 
999  // correct: g = (*(bayer-width) + bayer[1] + bayer[-1]) / 3;
1000  // faster:
1001  *rgb++ = (*(bayer - width - 1) + *(bayer - width + 1)) >> 1;
1002  *rgb++ = (*(bayer - width) + bayer[-1]) >> 1;
1003  *rgb++ = *bayer;
1004  ++bayer;
1005 
1006  *rgb++ = *(bayer - width);
1007  *rgb++ = *bayer;
1008  *rgb++ = bayer[-1];
1009  ++bayer;
1010 }
1011 
1012 } // end namespace firevision