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, 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