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
29namespace 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
43void
44bayerGBRG_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
90void
91bayerGBRG_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
275void
276bayerGBRG_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
363void
364bayerGBRG_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
551void
552bayerGRBG_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
589void
590bayerRGGB_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
627void
628bayerGRBG_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
812void
813bayerGRBG_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
847void
848bayerGRBG_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