Fawkes API  Fawkes Development Version
bayer.cpp
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