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, g, 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 } // end namespace firevision