Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * bayer.cpp - methods to convert bayer mosaic images to other formats 00004 * 00005 * Generated: Fri Aug 11 00:03:32 2006 00006 * Copyright 2005-2006 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <fvutils/color/bayer.h> 00025 #include <fvutils/color/colorspaces.h> 00026 #include <fvutils/color/yuv.h> 00027 #include <fvutils/color/rgbyuv.h> 00028 00029 namespace firevision { 00030 #if 0 /* just to make Emacs auto-indent happy */ 00031 } 00032 #endif 00033 00034 /* The basic information has been taken from 00035 * http://www-ise.stanford.edu/~tingchen/ 00036 */ 00037 00038 #define assign(y, u, v, y1, u1, v1, y2, u2, v2) { \ 00039 *y++ = y1; \ 00040 *y++ = y2; \ 00041 *u++ = ((u1 + u2) >> 1); \ 00042 *v++ = ((v1 + v2) >> 1); } 00043 00044 00045 void 00046 bayerGBRG_to_yuv422planar_nearest_neighbour(const unsigned char *bayer, unsigned char *yuv, 00047 unsigned int width, unsigned int height) 00048 { 00049 unsigned char *y = yuv; 00050 unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height); 00051 unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height); 00052 const unsigned char *b = bayer; 00053 00054 int y1, u1, v1, y2, u2, v2; 00055 int t1, t2; 00056 00057 for ( unsigned int h = 0; h < height; h += 2) { 00058 00059 // g b ... line 00060 for (unsigned int w = 0; w < width; w += 2) { 00061 t1 = b[width]; 00062 t2 = b[1]; 00063 RGB2YUV(t1, *b, t2, y1, u1, v1); 00064 ++b; 00065 00066 t1 = b[width - 1]; 00067 t2 = b[-1]; 00068 RGB2YUV(t1, t2, *b, y2, u2, v2); 00069 ++b; 00070 00071 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00072 } 00073 00074 // r g ... line 00075 for (unsigned int w = 0; w < width; w += 2) { 00076 t1 = b[1]; 00077 t2 = b[-width+1]; 00078 RGB2YUV(*b, t1, t2, y1, u1, v1); 00079 ++b; 00080 00081 t1 = b[-1]; 00082 t2 = b[-width]; 00083 RGB2YUV(t1, *b, t2, y2, u2, v2); 00084 ++b; 00085 00086 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00087 } 00088 } 00089 } 00090 00091 00092 00093 void 00094 bayerGBRG_to_yuv422planar_bilinear(const unsigned char *bayer, unsigned char *yuv, 00095 unsigned int width, unsigned int height) 00096 { 00097 unsigned char *y = yuv; 00098 unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height); 00099 unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height); 00100 const unsigned char *bf = bayer; 00101 00102 int y1, u1, v1, y2, u2, v2; 00103 int r, g, b; 00104 00105 // first line is special 00106 // g b ... line 00107 // not full data in first columns 00108 RGB2YUV(bf[width], *bf, bf[1], y1, u1, v1); 00109 ++bf; 00110 00111 r = (bf[width - 1] + bf[width + 1]) >> 1; 00112 // correct: 00113 // g = (bf[-1] + bf[width] + bf[1]) / 3; 00114 // faster: 00115 g = (bf[-1] + bf[1]) >> 1; 00116 RGB2YUV(r, g, *bf, y2, u2, v2); 00117 ++bf; 00118 00119 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00120 00121 // rest of first line 00122 for (unsigned int w = 2; w < width - 2; w += 2) { 00123 b = (bf[-1] + bf[1]) >> 1; 00124 RGB2YUV(bf[width], *bf, b, y1, u1, v1); 00125 ++bf; 00126 00127 r = (bf[width - 1] + bf[width + 1]) >> 1; 00128 // correct: 00129 // g = (bf[-1] + bf[width] + bf[1]) / 3; 00130 // faster: 00131 g = (bf[-1] + bf[1]) >> 1; 00132 RGB2YUV(r, g, *bf, y2, u2, v2); 00133 ++bf; 00134 00135 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00136 } 00137 00138 // not full data in last columns 00139 b = (bf[-1] + bf[1]) >> 1; 00140 RGB2YUV(bf[width], *bf, b, y1, u1, v1); 00141 ++bf; 00142 00143 g = (bf[-1] + bf[width]) >> 1; 00144 RGB2YUV(bf[width - 1], g, *bf, y2, u2, v2); 00145 ++bf; 00146 00147 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00148 00149 for ( unsigned int h = 1; h < height - 1; h += 2) { 00150 00151 // r g ... line 00152 // correct: g = (bf[-width] + bf[1] + bf[width]) / 3; 00153 // faster: 00154 g = (bf[-width] + bf[1]) >> 1; 00155 b = (bf[width-1] + bf[width+1]) >> 1; 00156 RGB2YUV(*bf, g, b, y1, u1, v1); 00157 ++bf; 00158 00159 r = (bf[-1] + bf[1]) >> 1; 00160 b = (bf[-width] + bf[width]) >> 1; 00161 RGB2YUV(r, *bf, b, y2, u2, v2); 00162 ++bf; 00163 00164 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00165 00166 for (unsigned int w = 2; w < width - 2; w += 2) { 00167 g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2; 00168 b = (bf[-width-1] + bf[-width+1] + bf[width-1] + bf[width+1]) >> 2; 00169 RGB2YUV(*bf, g, b, y1, u1, v1); 00170 ++bf; 00171 00172 r = (bf[-1] + bf[1]) >> 1; 00173 b = (bf[-width] + bf[width]) >> 1; 00174 RGB2YUV(r, *bf, b, y2, u2, v2); 00175 ++bf; 00176 00177 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00178 } 00179 00180 g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2; 00181 b = (bf[-width-1] + bf[-width+1] + bf[width-1] + bf[width+1]) >> 2; 00182 RGB2YUV(*bf, g, b, y1, u1, v1); 00183 ++bf; 00184 00185 b = (bf[-width] + bf[width]) >> 1; 00186 RGB2YUV(bf[-1], *bf, g, y2, u2, v2); 00187 ++bf; 00188 00189 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00190 00191 00192 00193 // g b ... line 00194 r = (bf[width] + bf[-width]) >> 1; 00195 RGB2YUV(r, *bf, bf[1], y1, u1, v1); 00196 ++bf; 00197 00198 r = (bf[-width-1] + bf[-width+1] + bf[width - 1] + bf[width + 1]) >> 2; 00199 g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2; 00200 RGB2YUV(r, g, *bf, y2, u2, v2); 00201 ++bf; 00202 00203 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00204 00205 for (unsigned int w = 2; w < width - 2; w += 2) { 00206 r = (bf[width] + bf[-width]) >> 1; 00207 b = (bf[-1] + bf[1]) >> 1; 00208 RGB2YUV(r, *bf, b, y1, u1, v1); 00209 ++bf; 00210 00211 r = (bf[-width-1] + bf[-width+1] + bf[width-1] + bf[width+1]) >> 2; 00212 g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2; 00213 RGB2YUV(r, g, *bf, y2, u2, v2); 00214 ++bf; 00215 00216 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00217 } 00218 00219 r = (bf[width] + bf[-width]) >> 1; 00220 b = (bf[-1] + bf[1]) >> 1; 00221 RGB2YUV(r, *bf, b, y1, u1, v1); 00222 ++bf; 00223 00224 r = (bf[-width-1] + bf[width-1]) >> 1; 00225 // correct: g = (bf[-width] + bf[width] + bf[-1]) / 3; 00226 // faster: 00227 g = (bf[-width] + bf[-1]) >> 1; 00228 RGB2YUV(r, g, *bf, y2, u2, v2); 00229 ++bf; 00230 00231 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00232 } 00233 00234 // last r g ... line 00235 // correct: g = (bf[-width] + bf[1] + bf[width]) / 3; 00236 // faster: 00237 g = (bf[-width] + bf[1]) >> 1; 00238 b = bf[-width+1]; 00239 RGB2YUV(*bf, g, b, y1, u1, v1); 00240 ++bf; 00241 00242 r = (bf[-1] + bf[1]) >> 1; 00243 b = bf[-width]; 00244 RGB2YUV(r, g, *bf, y2, u2, v2); 00245 ++bf; 00246 00247 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00248 00249 for (unsigned int w = 2; w < width - 2; w += 2) { 00250 // correct: g = (bf[-width] + bf[1] + bf[-1]) / 3 00251 // faster: 00252 g = (bf[-width] + bf[-1]) >> 1; 00253 b = (bf[-width-1] + bf[-width+1]) >> 1; 00254 RGB2YUV(*bf, g, b, y1, u1, v1); 00255 ++bf; 00256 00257 r = (bf[-1] + bf[1]) >> 1; 00258 b = bf[-width]; 00259 RGB2YUV(r, *bf, b, y2, u2, v2); 00260 ++bf; 00261 00262 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00263 } 00264 00265 // correct: g = (bf[-width] + bf[1] + bf[-1]) / 3; 00266 // faster: 00267 g = (bf[-width] + bf[-1]) >> 1; 00268 b = (bf[-width-1] + bf[-width+1]) >> 1; 00269 RGB2YUV(*bf, g, b, y1, u1, v1); 00270 ++bf; 00271 00272 b = bf[-width]; 00273 RGB2YUV(bf[-1], *bf, b, y2, u2, v2); 00274 ++bf; 00275 00276 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00277 00278 } 00279 00280 00281 void 00282 bayerGBRG_to_yuv422planar_bilinear2(const unsigned char *bayer, unsigned char *yuv, 00283 unsigned int width, unsigned int height) 00284 { 00285 unsigned char *y = yuv; 00286 unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height); 00287 unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height); 00288 const unsigned char *bf = bayer; 00289 00290 int y1, u1, v1, y2, u2, v2; 00291 int r, g, b; 00292 00293 // ignore first g b ... line 00294 bf += width; 00295 y += width; 00296 u += width >> 1; 00297 v += width >> 1; 00298 00299 for ( unsigned int h = 1; h < height - 1; h += 2) { 00300 00301 // r g ... line 00302 // ignore first two columns 00303 ++bf; ++bf; 00304 ++y; ++y; 00305 ++u; ++v; 00306 00307 for (unsigned int w = 2; w < width - 2; w += 2) { 00308 g = (bf[1] + bf[-1]) >> 1; 00309 b = (bf[width-1] + bf[width+1]) >> 1; 00310 RGB2YUV(*bf, g, b, y1, u1, v1); 00311 ++bf; 00312 00313 r = (bf[-1] + bf[1]) >> 1; 00314 b = (bf[-width] + bf[width]) >> 1; 00315 RGB2YUV(r, *bf, b, y2, u2, v2); 00316 ++bf; 00317 00318 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00319 } 00320 00321 // ignore last two columns 00322 ++bf; ++bf; 00323 ++y; ++y; 00324 ++u; ++v; 00325 00326 // g b ... line 00327 // ignore first two columns 00328 ++bf; ++bf; 00329 ++y; ++y; 00330 ++u; ++v; 00331 00332 for (unsigned int w = 2; w < width - 2; w += 2) { 00333 r = (bf[width] + bf[-width]) >> 1; 00334 b = (bf[-1] + bf[1]) >> 1; 00335 RGB2YUV(r, *bf, b, y1, u1, v1); 00336 ++bf; 00337 00338 r = (bf[width-1] + bf[width+1]) >> 1; 00339 g = (bf[1] + bf[width]) >> 1; 00340 RGB2YUV(r, g, *bf, y2, u2, v2); 00341 ++bf; 00342 00343 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00344 } 00345 00346 // ignore last two columns 00347 ++bf; ++bf; 00348 ++y; ++y; 00349 ++u; ++v; 00350 } 00351 00352 // ignore last r g ... line 00353 00354 } 00355 00356 /* Not faster in benchmarks 00357 void 00358 bayerGBRG_to_yuv422planar_bilinear2(const unsigned char *bayer, unsigned char *yuv, 00359 unsigned int width, unsigned int height) 00360 { 00361 unsigned char *y = yuv; 00362 unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height); 00363 unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height); 00364 unsigned char *bf = bayer; 00365 00366 int y1, u1, v1, y2, u2, v2; 00367 int r, g, b; 00368 00369 // first line is special 00370 // g b ... line 00371 // not full data in first columns 00372 RGB2YUV(*(bf + width), *bf, *(bf + 1), y1, u1, v1); 00373 ++bf; 00374 00375 r = (*(bf + width - 1) + *(bf + width + 1)) >> 1; 00376 // correct: 00377 // g = (*(bf - 1) + *(bf + width) + *(bf + 1)) / 3; 00378 // faster: 00379 g = (*(bf -1) + *(bf +1)) >> 1; 00380 RGB2YUV(r, g, *bf, y2, u2, v2); 00381 ++bf; 00382 00383 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00384 00385 // rest of first line 00386 for (unsigned int w = 2; w < width - 2; w += 2) { 00387 b = (*(bf - 1) + *(bf + 1)) >> 1; 00388 RGB2YUV(*(bf + width), *bf, b, y1, u1, v1); 00389 ++bf; 00390 00391 r = (*(bf + width - 1) + *(bf + width + 1)) >> 1; 00392 // correct: 00393 // g = (*(bf - 1) + *(bf + width) + *(bf + 1)) / 3; 00394 // faster: 00395 g = (*(bf - 1) + *(bf + 1)) >> 1; 00396 RGB2YUV(r, g, *bf, y2, u2, v2); 00397 ++bf; 00398 00399 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00400 } 00401 00402 // not full data in last columns 00403 b = (*(bf - 1) + *(bf + 1)) >> 1; 00404 RGB2YUV(*(bf + width), *bf, b, y1, u1, v1); 00405 ++bf; 00406 00407 g = (*(bf - 1) + *(bf + width)) >> 1; 00408 RGB2YUV(*(bf + width - 1), g, *bf, y2, u2, v2); 00409 ++bf; 00410 00411 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00412 00413 for ( unsigned int h = 1; h < height - 1; h += 2) { 00414 00415 // r g ... line 00416 // correct: g = (*(bf - width) + *(bf + 1) + *(bf + width)) / 3; 00417 // faster: 00418 g = (*(bf - width) + *(bf + 1)) >> 1; 00419 b = (*(bf + width - 1) + *(bf + width + 1)) >> 1; 00420 RGB2YUV(*bf, g, b, y1, u1, v1); 00421 ++bf; 00422 00423 r = (*(bf - 1) + *(bf + 1)) >> 1; 00424 b = (*(bf - width) + *(bf + width)) >> 1; 00425 RGB2YUV(r, *bf, g, y2, u2, v2); 00426 ++bf; 00427 00428 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00429 00430 for (unsigned int w = 2; w < width - 2; w += 2) { 00431 g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2; 00432 b = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2; 00433 RGB2YUV(*bf, g, b, y1, u1, v1); 00434 ++bf; 00435 00436 r = (*(bf - 1) + *(bf + 1)) >> 1; 00437 b = (*(bf - width) + *(bf + width)) >> 1; 00438 RGB2YUV(r, *bf, b, y2, u2, v2); 00439 ++bf; 00440 00441 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00442 } 00443 00444 g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2; 00445 b = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2; 00446 RGB2YUV(*bf, g, b, y1, u1, v1); 00447 ++bf; 00448 00449 b = (*(bf - width) + *(bf + width)) >> 1; 00450 RGB2YUV(*(bf - 1), *bf, g, y2, u2, v2); 00451 ++bf; 00452 00453 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00454 00455 00456 00457 // g b ... line 00458 r = (*(bf + width) + *(bf - width)) >> 1; 00459 RGB2YUV(r, *bf, *(bf + 1), y1, u1, v1); 00460 ++bf; 00461 00462 r = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2; 00463 g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2; 00464 RGB2YUV(r, g, *bf, y2, u2, v2); 00465 ++bf; 00466 00467 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00468 00469 for (unsigned int w = 2; w < width - 2; w += 2) { 00470 r = (*(bf + width) + *(bf - width)) >> 1; 00471 b = (*(bf - 1) + *(bf + 1)) >> 1; 00472 RGB2YUV(r, *bf, b, y1, u1, v1); 00473 ++bf; 00474 00475 r = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2; 00476 g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2; 00477 RGB2YUV(r, g, *bf, y2, u2, v2); 00478 ++bf; 00479 00480 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00481 } 00482 00483 r = (*(bf + width) + *(bf - width)) >> 1; 00484 b = (*(bf - 1) + *(bf + 1)) >> 1; 00485 RGB2YUV(r, *bf, b, y1, u1, v1); 00486 ++bf; 00487 00488 r = (*(bf - width - 1) + *(bf + width - 1)) >> 1; 00489 // correct: g = (*(bf - width) + *(bf + width) + *(bf - 1)) / 3; 00490 // faster: 00491 g = (*(bf - width) + *(bf - 1)) >> 1; 00492 RGB2YUV(r, g, *bf, y2, u2, v2); 00493 ++bf; 00494 00495 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00496 } 00497 00498 // last r g ... line 00499 // correct: g = (*(bf - width) + *(bf + 1) + *(bf + width)) / 3; 00500 // faster: 00501 g = (*(bf - width) + *(bf + 1)) >> 1; 00502 b = *(bf - width + 1); 00503 RGB2YUV(*bf, g, b, y1, u1, v1); 00504 ++bf; 00505 00506 r = (*(bf - 1) + *(bf + 1)) >> 1; 00507 b = *(bf - width); 00508 RGB2YUV(r, g, *bf, y2, u2, v2); 00509 ++bf; 00510 00511 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00512 00513 for (unsigned int w = 2; w < width - 2; w += 2) { 00514 // correct: g = (*(bf - width) + *(bf + 1) + *(bf - 1)) / 3 00515 // faster: 00516 g = (*(bf - width) + *(bf - 1)) >> 1; 00517 b = (*(bf - width - 1) + *(bf - width + 1)) >> 1; 00518 RGB2YUV(*bf, g, b, y1, u1, v1); 00519 ++bf; 00520 00521 r = (*(bf - 1) + *(bf + 1)) >> 1; 00522 b = *(bf - width); 00523 RGB2YUV(r, *bf, b, y2, u2, v2); 00524 ++bf; 00525 00526 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00527 } 00528 00529 // correct: g = (*(bf - width) + *(bf + 1) + *(bf - 1)) / 3; 00530 // faster: 00531 g = (*(bf - width) + *(bf - 1)) >> 1; 00532 b = (*(bf - width - 1) + *(bf - width + 1)) >> 1; 00533 RGB2YUV(*bf, g, b, y1, u1, v1); 00534 ++bf; 00535 00536 b = *(bf - width); 00537 RGB2YUV(*(bf - 1), *bf, b, y2, u2, v2); 00538 ++bf; 00539 00540 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00541 00542 } 00543 */ 00544 00545 void 00546 bayerGRBG_to_yuv422planar_nearest_neighbour(const unsigned char *bayer, 00547 unsigned char *yuv, 00548 unsigned int width, 00549 unsigned int height) 00550 { 00551 unsigned char *y = yuv; 00552 unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height); 00553 unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height); 00554 const unsigned char *b = bayer; 00555 00556 int y1, u1, v1, y2, u2, v2; 00557 00558 for ( unsigned int h = 0; h < height; h += 2) { 00559 00560 // g r ... line 00561 for (unsigned int w = 0; w < width; w += 2) { 00562 RGB2YUV(b[1], b[width], *b, y1, u1, v1); 00563 ++b; 00564 00565 RGB2YUV(*b, b[-1], b[width - 1], y2, u2, v2); 00566 ++b; 00567 00568 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00569 } 00570 00571 // b g ... line 00572 for (unsigned int w = 0; w < width; w += 2) { 00573 RGB2YUV(*(b-width+1), b[1], *b, y1, u1, v1); 00574 ++b; 00575 00576 RGB2YUV(*(b-width), *b, b[-1], y2, u2, v2); 00577 ++b; 00578 00579 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00580 } 00581 } 00582 } 00583 00584 00585 void 00586 bayerRGGB_to_yuv422planar_nearest_neighbour(const unsigned char *bayer, 00587 unsigned char *yuv, 00588 unsigned int width, 00589 unsigned int height) 00590 { 00591 unsigned char *y = yuv; 00592 unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height); 00593 unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height); 00594 const unsigned char *b = bayer; 00595 00596 int y1, u1, v1, y2, u2, v2; 00597 00598 for ( unsigned int h = 0; h < height; h += 2) { 00599 00600 // r g ... line 00601 for (unsigned int w = 0; w < width; w += 2) { 00602 RGB2YUV(*b, b[1], b[width+1], y1, u1, v1); 00603 ++b; 00604 00605 RGB2YUV(b[-1], *b, b[width], y2, u2, v2); 00606 ++b; 00607 00608 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00609 } 00610 00611 // g b ... line 00612 for (unsigned int w = 0; w < width; w += 2) { 00613 RGB2YUV(*(b-width), *b, b[1], y1, u1, v1); 00614 ++b; 00615 00616 RGB2YUV(*(b-width-1), b[-1], *b, y2, u2, v2); 00617 ++b; 00618 00619 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00620 } 00621 } 00622 } 00623 00624 void 00625 bayerGRBG_to_yuv422planar_bilinear(const unsigned char *bayer, unsigned char *yuv, 00626 unsigned int width, unsigned int height) 00627 { 00628 unsigned char *y = yuv; 00629 unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height); 00630 unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height); 00631 const unsigned char *bf = bayer; 00632 00633 int y1, u1, v1, y2, u2, v2; 00634 int r, g, b; 00635 00636 // first line is special 00637 // g r ... line 00638 // not full data in first columns 00639 RGB2YUV(bf[1], *bf, bf[width], y1, u1, v1); 00640 ++bf; 00641 00642 b = (bf[width - 1] + bf[width + 1]) >> 1; 00643 // correct: 00644 // g = (bf[-1] + bf[width] + bf[1]) / 3; 00645 // faster: 00646 g = (bf[-1] + bf[1]) >> 1; 00647 RGB2YUV(*bf, g, b, y2, u2, v2); 00648 ++bf; 00649 00650 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00651 00652 // rest of first line 00653 for (unsigned int w = 2; w < width - 2; w += 2) { 00654 r = (bf[-1] + bf[1]) >> 1; 00655 RGB2YUV(r, *bf, bf[width], y1, u1, v1); 00656 ++bf; 00657 00658 b = (bf[width - 1] + bf[width + 1]) >> 1; 00659 // correct: 00660 // g = (bf[-1] + bf[width] + bf[1]) / 3; 00661 // faster: 00662 g = (bf[-1] + bf[1]) >> 1; 00663 RGB2YUV(*bf, g, b, y2, u2, v2); 00664 ++bf; 00665 00666 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00667 } 00668 00669 // not full data in last columns 00670 r = (bf[-1] + bf[1]) >> 1; 00671 RGB2YUV(r, *bf, bf[width], y1, u1, v1); 00672 ++bf; 00673 00674 g = (bf[-1] + bf[width]) >> 1; 00675 RGB2YUV(*bf, g, bf[width - 1], y2, u2, v2); 00676 ++bf; 00677 00678 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00679 00680 for ( unsigned int h = 1; h < height - 1; h += 2) { 00681 00682 // b g ... line 00683 // correct: g = (*(bf-width) + bf[1] + bf[width]) / 3; 00684 // faster: 00685 g = (*(bf-width) + bf[1]) >> 1; 00686 r = (*(bf-width+1) + bf[width+1]) >> 1; 00687 RGB2YUV(r, g, *bf, y1, u1, v1); 00688 ++bf; 00689 00690 b = (bf[-1] + bf[1]) >> 1; 00691 r = (*(bf-width) + bf[width]) >> 1; 00692 RGB2YUV(r, *bf, g, y2, u2, v2); 00693 ++bf; 00694 00695 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00696 00697 for (unsigned int w = 2; w < width - 2; w += 2) { 00698 g = (*(bf-width) + bf[1] + bf[width] + bf[-1]) >> 2; 00699 r = (*(bf-width-1) + *(bf-width+1) + bf[width-1] + bf[width+1]) >> 2; 00700 RGB2YUV(r, g, *bf, y1, u1, v1); 00701 ++bf; 00702 00703 b = (bf[-1] + bf[1]) >> 1; 00704 r = ( *(bf-width) + bf[width]) >> 1; 00705 RGB2YUV(r, *bf, b, y2, u2, v2); 00706 ++bf; 00707 00708 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00709 } 00710 00711 g = (*(bf-width) + bf[1] + bf[width] + bf[-1]) >> 2; 00712 r = (*(bf-width-1) + *(bf-width+1) + bf[width-1] + bf[width+1]) >> 2; 00713 RGB2YUV(r, g, *bf, y1, u1, v1); 00714 ++bf; 00715 00716 r = (*(bf-width) + bf[width]) >> 1; 00717 RGB2YUV(r, *bf, bf[-1], y2, u2, v2); 00718 ++bf; 00719 00720 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00721 00722 00723 // g r ... line 00724 b = (bf[width] + *(bf-width)) >> 1; 00725 RGB2YUV(bf[1], *bf, b, y1, u1, v1); 00726 ++bf; 00727 00728 b = (*(bf-width-1) + *(bf-width+1) + bf[width - 1] + bf[width + 1]) >> 2; 00729 g = (*(bf-width) + bf[1] + bf[width] + bf[-1]) >> 2; 00730 RGB2YUV(*bf, g, b, y2, u2, v2); 00731 ++bf; 00732 00733 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00734 00735 for (unsigned int w = 2; w < width - 2; w += 2) { 00736 b = (bf[width] + *(bf-width)) >> 1; 00737 r = (bf[-1] + bf[1]) >> 1; 00738 RGB2YUV(r, *bf, b, y1, u1, v1); 00739 ++bf; 00740 00741 b = (*(bf-width-1) + *(bf-width+1) + bf[width-1] + bf[width+1]) >> 2; 00742 g = (*(bf-width) + bf[1] + bf[width] + bf[-1]) >> 2; 00743 RGB2YUV(*bf, g, b, y2, u2, v2); 00744 ++bf; 00745 00746 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00747 } 00748 00749 b = (bf[width] + *(bf-width)) >> 1; 00750 r = (bf[-1] + bf[1]) >> 1; 00751 RGB2YUV(r, *bf, b, y1, u1, v1); 00752 ++bf; 00753 00754 b = (*(bf-width-1) + bf[width-1]) >> 1; 00755 // correct: g = (*(bf-width) + bf[width] + bf[-1]) / 3; 00756 // faster: 00757 g = (*(bf-width) + bf[-1]) >> 1; 00758 RGB2YUV(*bf, g, r, y2, u2, v2); 00759 ++bf; 00760 00761 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00762 } 00763 00764 // last b g ... line 00765 // correct: g = (*(bf-width) + bf[1] + bf[width]) / 3; 00766 // faster: 00767 g = (*(bf-width) + bf[1]) >> 1; 00768 r = *(bf-width+1); 00769 RGB2YUV(r, g, *bf, y1, u1, v1); 00770 ++bf; 00771 00772 b = (bf[-1] + bf[1]) >> 1; 00773 r = *(bf-width); 00774 RGB2YUV(r, *bf, b, y2, u2, v2); 00775 ++bf; 00776 00777 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00778 00779 for (unsigned int w = 2; w < width - 2; w += 2) { 00780 // correct: g = (*(bf-width) + bf[1] + bf[-1]) / 3 00781 // faster: 00782 g = (*(bf-width) + bf[-1]) >> 1; 00783 r = (*(bf-width-1) + *(bf-width+1)) >> 1; 00784 RGB2YUV(r, g, *bf, y1, u1, v1); 00785 ++bf; 00786 00787 b = (bf[-1] + bf[1]) >> 1; 00788 r = *(bf-width); 00789 RGB2YUV(r, *bf, b, y2, u2, v2); 00790 ++bf; 00791 00792 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00793 } 00794 00795 // correct: g = (*(bf-width) + bf[1] + bf[-1]) / 3; 00796 // faster: 00797 g = (*(bf-width) + bf[-1]) >> 1; 00798 r = (*(bf-width-1) + *(bf-width+1)) >> 1; 00799 RGB2YUV(r, g, *bf, y1, u1, v1); 00800 ++bf; 00801 00802 r = *(bf-width); 00803 RGB2YUV(r, *bf, bf[-1], y2, u2, v2); 00804 ++bf; 00805 00806 assign(y, u, v, y1, u1, v1, y2, u2, v2); 00807 00808 } 00809 00810 00811 void 00812 bayerGRBG_to_rgb_nearest_neighbour(const unsigned char *bayer, unsigned char *rgb, 00813 unsigned int width, unsigned int height) 00814 { 00815 for (register unsigned int h = 0; h < height; h += 2) { 00816 // g r ... line 00817 for (register unsigned int w = 0; w < width; w += 2) { 00818 *rgb++ = bayer[1]; 00819 *rgb++ = bayer[width]; 00820 *rgb++ = *bayer; 00821 ++bayer; 00822 00823 *rgb++ = *bayer; 00824 *rgb++ = bayer[-1]; 00825 *rgb++ = bayer[width - 1]; 00826 ++bayer; 00827 } 00828 00829 // b g ... line 00830 for (register unsigned int w = 0; w < width; w += 2) { 00831 *rgb++ = *(bayer-width+1); 00832 *rgb++ = bayer[1]; 00833 *rgb++ = *bayer; 00834 ++bayer; 00835 00836 *rgb++ = *(bayer-width); 00837 *rgb++ = *bayer; 00838 *rgb++ = bayer[-1]; 00839 ++bayer; 00840 } 00841 } 00842 } 00843 00844 00845 void 00846 bayerGRBG_to_rgb_bilinear(const unsigned char *bayer, unsigned char *rgb, 00847 unsigned int width, unsigned int height) 00848 { 00849 // first line is special 00850 // g r ... line 00851 // not full data in first columns 00852 *rgb++ = bayer[1]; 00853 *rgb++ = *bayer; 00854 *rgb++ = bayer[width]; 00855 ++bayer; 00856 00857 // correct: 00858 // g = (bayer[-1] + bayer[width] + bayer[1]) / 3; 00859 // faster: 00860 *rgb++ = *bayer; 00861 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00862 *rgb++ = (bayer[width - 1] + bayer[width + 1]) >> 1; 00863 ++bayer; 00864 00865 // rest of first line 00866 for (unsigned int w = 2; w < width - 2; w += 2) { 00867 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00868 *rgb++ = *bayer; 00869 *rgb++ = bayer[width]; 00870 ++bayer; 00871 00872 // correct: 00873 // g = (bayer[-1] + bayer[width] + bayer[1]) / 3; 00874 // faster: 00875 *rgb++ = *bayer; 00876 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00877 *rgb++ = (bayer[width - 1] + bayer[width + 1]) >> 1; 00878 ++bayer; 00879 } 00880 00881 // not full data in last columns 00882 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00883 *rgb++ = *bayer; 00884 *rgb++ = bayer[width]; 00885 ++bayer; 00886 00887 *rgb++ = *bayer; 00888 *rgb++ = (bayer[-1] + bayer[width]) >> 1; 00889 *rgb++ = bayer[width - 1]; 00890 ++bayer; 00891 00892 for ( unsigned int h = 1; h < height - 1; h += 2) { 00893 // b g ... line 00894 // correct: g = (*(bayer-width) + bayer[1] + bayer[width]) / 3; 00895 // faster: 00896 *rgb++ = (*(bayer-width+1) + bayer[width+1]) >> 1; 00897 *rgb++ = (*(bayer-width) + bayer[1]) >> 1; 00898 *rgb++ = *bayer; 00899 ++bayer; 00900 00901 *rgb++ = (*(bayer-width) + bayer[width]) >> 1; 00902 *rgb++ = *bayer; 00903 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00904 ++bayer; 00905 00906 for (unsigned int w = 2; w < width - 2; w += 2) { 00907 *rgb++ = (*(bayer-width-1) + *(bayer-width+1) + bayer[width-1] + bayer[width+1]) >> 2; 00908 *rgb++ = (*(bayer-width) + bayer[1] + bayer[width] + bayer[-1]) >> 2; 00909 *rgb++ = *bayer; 00910 ++bayer; 00911 00912 *rgb++ = (*(bayer-width) + bayer[width]) >> 1; 00913 *rgb++ = *bayer; 00914 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00915 ++bayer; 00916 } 00917 00918 *rgb++ = (*(bayer-width-1) + *(bayer-width+1) + bayer[width-1] + bayer[width+1]) >> 2; 00919 *rgb++ = (*(bayer-width) + bayer[1] + bayer[width] + bayer[-1]) >> 2; 00920 *rgb++ = *bayer; 00921 ++bayer; 00922 00923 *rgb++ = (*(bayer-width) + bayer[width]) >> 1; 00924 *rgb++ = *bayer; 00925 *rgb++ = bayer[-1]; 00926 ++bayer; 00927 00928 00929 // g r ... line 00930 *rgb++ = bayer[1]; 00931 *rgb++ = *bayer; 00932 *rgb++ = (bayer[width] + *(bayer-width)) >> 1; 00933 ++bayer; 00934 00935 *rgb++ = *bayer; 00936 *rgb++ = (*(bayer-width) + bayer[1] + bayer[width] + bayer[-1]) >> 2; 00937 *rgb++ = (*(bayer-width-1) + *(bayer-width+1) + bayer[width - 1] + bayer[width + 1]) >> 2; 00938 ++bayer; 00939 00940 for (unsigned int w = 2; w < width - 2; w += 2) { 00941 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00942 *rgb++ = *bayer; 00943 *rgb++ = (bayer[width] + *(bayer-width)) >> 1; 00944 ++bayer; 00945 00946 *rgb++ = *bayer; 00947 *rgb++ = (*(bayer-width) + bayer[1] + bayer[width] + bayer[-1]) >> 2; 00948 *rgb++ = (*(bayer-width-1) + *(bayer-width+1) + bayer[width-1] + bayer[width+1]) >> 2; 00949 ++bayer; 00950 } 00951 00952 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00953 *rgb++ = *bayer; 00954 *rgb++ = (bayer[width] + *(bayer-width)) >> 1; 00955 ++bayer; 00956 00957 // correct: g = (*(bayer-width) + bayer[width] + bayer[-1]) / 3; 00958 // faster: 00959 *rgb++ = *bayer; 00960 *rgb++ = (*(bayer-width) + bayer[-1]) >> 1; 00961 *rgb++ = (*(bayer-width-1) + bayer[width-1]) >> 1; 00962 ++bayer; 00963 } 00964 00965 // last b g ... line 00966 // correct: g = (*(bayer-width) + bayer[1] + bayer[width]) / 3; 00967 // faster: 00968 *rgb++ = *(bayer-width+1); 00969 *rgb++ = (*(bayer-width) + bayer[1]) >> 1; 00970 *rgb++ = *bayer; 00971 ++bayer; 00972 00973 *rgb++ = *(bayer-width); 00974 *rgb++ = *bayer; 00975 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00976 ++bayer; 00977 00978 for (unsigned int w = 2; w < width - 2; w += 2) { 00979 // correct: g = (*(bayer-width) + bayer[1] + bayer[-1]) / 3 00980 // faster: 00981 *rgb++ = (*(bayer-width-1) + *(bayer-width+1)) >> 1; 00982 *rgb++ = (*(bayer-width) + bayer[-1]) >> 1; 00983 *rgb++ = *bayer; 00984 ++bayer; 00985 00986 *rgb++ = *(bayer-width); 00987 *rgb++ = *bayer; 00988 *rgb++ = (bayer[-1] + bayer[1]) >> 1; 00989 ++bayer; 00990 } 00991 00992 // correct: g = (*(bayer-width) + bayer[1] + bayer[-1]) / 3; 00993 // faster: 00994 *rgb++ = (*(bayer-width-1) + *(bayer-width+1)) >> 1; 00995 *rgb++ = (*(bayer-width) + bayer[-1]) >> 1; 00996 *rgb++ = *bayer; 00997 ++bayer; 00998 00999 *rgb++ = *(bayer-width); 01000 *rgb++ = *bayer; 01001 *rgb++ = bayer[-1]; 01002 ++bayer; 01003 } 01004 01005 01006 } // end namespace firevision