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