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 /* The basic information has been taken from
00030  * http://www-ise.stanford.edu/~tingchen/
00031  */
00032
00033 #define assign(y, u, v, y1, u1, v1, y2, u2, v2) { \
00034     *y++ = y1;                                    \
00035     *y++ = y2;                                    \
00036     *u++ = ((u1 + u2) >> 1);                      \
00037     *v++ = ((v1 + v2) >> 1); }
00038 
00039
00040 void
00041 bayerGBRG_to_yuv422planar_nearest_neighbour(const unsigned char *bayer, unsigned char *yuv,
00042                                             unsigned int width, unsigned int height)
00043 {
00044   unsigned char *y = yuv;
00045   unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height);
00046   unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height);
00047   const unsigned char *b = bayer;
00048
00049   int y1, u1, v1, y2, u2, v2;
00050   int t1, t2;
00051
00052   for ( unsigned int h = 0; h < height; h += 2) {
00053
00054     // g  b  ... line
00055     for (unsigned int w = 0; w < width; w += 2) {
00056       t1 = b[width];
00057       t2 = b[1];
00058       RGB2YUV(t1, *b, t2, y1, u1, v1);
00059       ++b;
00060
00061       t1 = b[width - 1];
00062       t2 = b[-1];
00063       RGB2YUV(t1, t2, *b, y2, u2, v2);
00064       ++b;
00065
00066       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00067     }
00068
00069     // r  g  ... line
00070     for (unsigned int w = 0; w < width; w += 2) {
00071       t1 = b[1];
00072       t2 = b[-width+1];
00073       RGB2YUV(*b, t1, t2, y1, u1, v1);
00074       ++b;
00075
00076       t1 = b[-1];
00077       t2 = b[-width];
00078       RGB2YUV(t1, *b, t2, y2, u2, v2);
00079       ++b;
00080
00081       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00082     }
00083   }
00084 }
00085
00086
00087
00088 void
00089 bayerGBRG_to_yuv422planar_bilinear(const unsigned char *bayer, unsigned char *yuv,
00090                                    unsigned int width, unsigned int height)
00091 {
00092   unsigned char *y = yuv;
00093   unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height);
00094   unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height);
00095   const unsigned char *bf = bayer;
00096
00097   int y1, u1, v1, y2, u2, v2;
00098   int r, g, b;
00099
00100   // first line is special
00101   // g  b  ... line
00102   // not full data in first columns
00103   RGB2YUV(bf[width], *bf, bf[1], y1, u1, v1);
00104   ++bf;
00105
00106   r = (bf[width - 1] + bf[width + 1]) >> 1;
00107   // correct:
00108   // g = (bf[-1] + bf[width] + bf[1]) / 3;
00109   // faster:
00110   g = (bf[-1] + bf[1]) >> 1;
00111   RGB2YUV(r, g, *bf, y2, u2, v2);
00112   ++bf;
00113
00114   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00115
00116   // rest of first line
00117   for (unsigned int w = 2; w < width - 2; w += 2) {
00118     b = (bf[-1] + bf[1]) >> 1;
00119     RGB2YUV(bf[width], *bf, b, y1, u1, v1);
00120     ++bf;
00121
00122     r = (bf[width - 1] + bf[width + 1]) >> 1;
00123     // correct:
00124     // g = (bf[-1] + bf[width] + bf[1]) / 3;
00125     // faster:
00126     g = (bf[-1] + bf[1]) >> 1;
00127     RGB2YUV(r, g, *bf, y2, u2, v2);
00128     ++bf;
00129
00130     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00131   }
00132
00133   // not full data in last columns
00134   b = (bf[-1] + bf[1]) >> 1;
00135   RGB2YUV(bf[width], *bf, b, y1, u1, v1);
00136   ++bf;
00137
00138   g = (bf[-1] + bf[width]) >> 1;
00139   RGB2YUV(bf[width - 1], g, *bf, y2, u2, v2);
00140   ++bf;
00141
00142   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00143
00144   for ( unsigned int h = 1; h < height - 1; h += 2) {
00145
00146     // r  g  ... line
00147     // correct: g = (bf[-width] + bf[1] + bf[width]) / 3;
00148     // faster:
00149     g = (bf[-width] + bf[1]) >> 1;
00150     b = (bf[width-1] + bf[width+1]) >> 1;
00151     RGB2YUV(*bf, g, b, y1, u1, v1);
00152     ++bf;
00153
00154     r = (bf[-1] + bf[1]) >> 1;
00155     b = (bf[-width] + bf[width]) >> 1;
00156     RGB2YUV(r, *bf, g, y2, u2, v2);
00157     ++bf;
00158
00159     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00160
00161     for (unsigned int w = 2; w < width - 2; w += 2) {
00162       g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
00163       b = (bf[-width-1] + bf[-width+1] + bf[width-1] + bf[width+1]) >> 2;
00164       RGB2YUV(*bf, g, b, y1, u1, v1);
00165       ++bf;
00166
00167       r = (bf[-1] + bf[1]) >> 1;
00168       b = (bf[-width] + bf[width]) >> 1;
00169       RGB2YUV(r, *bf, b, y2, u2, v2);
00170       ++bf;
00171
00172       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00173     }
00174
00175     g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
00176     b = (bf[-width-1] + bf[-width+1] + bf[width-1] + bf[width+1]) >> 2;
00177     RGB2YUV(*bf, g, b, y1, u1, v1);
00178     ++bf;
00179
00180     b = (bf[-width] + bf[width]) >> 1;
00181     RGB2YUV(bf[-1], *bf, g, y2, u2, v2);
00182     ++bf;
00183
00184     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00185
00186
00187
00188     // g  b  ... line
00189     r = (bf[width] + bf[-width]) >> 1;
00190     RGB2YUV(r, *bf, bf[1], y1, u1, v1);
00191     ++bf;
00192
00193     r = (bf[-width-1] + bf[-width+1] + bf[width - 1] + bf[width + 1]) >> 2;
00194     g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
00195     RGB2YUV(r, g, *bf, y2, u2, v2);
00196     ++bf;
00197
00198     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00199
00200     for (unsigned int w = 2; w < width - 2; w += 2) {
00201       r = (bf[width] + bf[-width]) >> 1;
00202       b = (bf[-1] + bf[1]) >> 1;
00203       RGB2YUV(r, *bf, b, y1, u1, v1);
00204       ++bf;
00205
00206       r = (bf[-width-1] + bf[-width+1] + bf[width-1] + bf[width+1]) >> 2;
00207       g = (bf[-width] + bf[1] + bf[width] + bf[-1]) >> 2;
00208       RGB2YUV(r, g, *bf, y2, u2, v2);
00209       ++bf;
00210
00211       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00212     }
00213
00214     r = (bf[width] + bf[-width]) >> 1;
00215     b = (bf[-1] + bf[1]) >> 1;
00216     RGB2YUV(r, *bf, b, y1, u1, v1);
00217     ++bf;
00218
00219     r = (bf[-width-1] + bf[width-1]) >> 1;
00220     // correct: g = (bf[-width] + bf[width] + bf[-1]) / 3;
00221     // faster:
00222     g = (bf[-width] + bf[-1]) >> 1;
00223     RGB2YUV(r, g, *bf, y2, u2, v2);
00224     ++bf;
00225
00226     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00227   }
00228
00229   // last r  g  ... line
00230   // correct: g = (bf[-width] + bf[1] + bf[width]) / 3;
00231   // faster:
00232   g = (bf[-width] + bf[1]) >> 1;
00233   b = bf[-width+1];
00234   RGB2YUV(*bf, g, b, y1, u1, v1);
00235   ++bf;
00236
00237   r = (bf[-1] + bf[1]) >> 1;
00238   b = bf[-width];
00239   RGB2YUV(r, g, *bf, y2, u2, v2);
00240   ++bf;
00241
00242   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00243
00244   for (unsigned int w = 2; w < width - 2; w += 2) {
00245     // correct: g = (bf[-width] + bf[1] + bf[-1]) / 3
00246     // faster:
00247     g = (bf[-width] + bf[-1]) >> 1;
00248     b = (bf[-width-1] + bf[-width+1]) >> 1;
00249     RGB2YUV(*bf, g, b, y1, u1, v1);
00250     ++bf;
00251
00252     r = (bf[-1] + bf[1]) >> 1;
00253     b = bf[-width];
00254     RGB2YUV(r, *bf, b, y2, u2, v2);
00255     ++bf;
00256
00257     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00258   }
00259
00260   // correct: g = (bf[-width] + bf[1] + bf[-1]) / 3;
00261   // faster:
00262   g = (bf[-width] + bf[-1]) >> 1;
00263   b = (bf[-width-1] + bf[-width+1]) >> 1;
00264   RGB2YUV(*bf, g, b, y1, u1, v1);
00265   ++bf;
00266
00267   b = bf[-width];
00268   RGB2YUV(bf[-1], *bf, b, y2, u2, v2);
00269   ++bf;
00270
00271   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00272
00273 }
00274
00275
00276 void
00277 bayerGBRG_to_yuv422planar_bilinear2(const unsigned char *bayer, unsigned char *yuv,
00278                                    unsigned int width, unsigned int height)
00279 {
00280   unsigned char *y = yuv;
00281   unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height);
00282   unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height);
00283   const unsigned char *bf = bayer;
00284
00285   int y1, u1, v1, y2, u2, v2;
00286   int r, g, b;
00287
00288   // ignore first g  b  ... line
00289   bf += width;
00290   y  += width;
00291   u  += width >> 1;
00292   v  += width >> 1;
00293
00294   for ( unsigned int h = 1; h < height - 1; h += 2) {
00295
00296     // r  g  ... line
00297     // ignore first two columns
00298     ++bf; ++bf;
00299     ++y; ++y;
00300     ++u; ++v;
00301
00302     for (unsigned int w = 2; w < width - 2; w += 2) {
00303       g = (bf[1] + bf[-1]) >> 1;
00304       b = (bf[width-1] + bf[width+1]) >> 1;
00305       RGB2YUV(*bf, g, b, y1, u1, v1);
00306       ++bf;
00307
00308       r = (bf[-1] + bf[1]) >> 1;
00309       b = (bf[-width] + bf[width]) >> 1;
00310       RGB2YUV(r, *bf, b, y2, u2, v2);
00311       ++bf;
00312
00313       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00314     }
00315
00316     // ignore last two columns
00317     ++bf; ++bf;
00318     ++y; ++y;
00319     ++u; ++v;
00320
00321     // g  b  ... line
00322     // ignore first two columns
00323     ++bf; ++bf;
00324     ++y; ++y;
00325     ++u; ++v;
00326
00327     for (unsigned int w = 2; w < width - 2; w += 2) {
00328       r = (bf[width] + bf[-width]) >> 1;
00329       b = (bf[-1] + bf[1]) >> 1;
00330       RGB2YUV(r, *bf, b, y1, u1, v1);
00331       ++bf;
00332
00333       r = (bf[width-1] + bf[width+1]) >> 1;
00334       g = (bf[1] + bf[width]) >> 1;
00335       RGB2YUV(r, g, *bf, y2, u2, v2);
00336       ++bf;
00337
00338       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00339     }
00340
00341     // ignore last two columns
00342     ++bf; ++bf;
00343     ++y; ++y;
00344     ++u; ++v;
00345   }
00346
00347   // ignore last r  g  ... line
00348
00349 }
00350
00351 /* Not faster in benchmarks
00352 void
00353 bayerGBRG_to_yuv422planar_bilinear2(const unsigned char *bayer, unsigned char *yuv,
00354                                     unsigned int width, unsigned int height)
00355 {
00356   unsigned char *y = yuv;
00357   unsigned char *u = YUV422_PLANAR_U_PLANE(yuv, width, height);
00358   unsigned char *v = YUV422_PLANAR_V_PLANE(yuv, width, height);
00359   unsigned char *bf = bayer;
00360 
00361   int y1, u1, v1, y2, u2, v2;
00362   int r, g, b;
00363 
00364   // first line is special
00365   // g  b  ... line
00366   // not full data in first columns
00367   RGB2YUV(*(bf + width), *bf, *(bf + 1), y1, u1, v1);
00368   ++bf;
00369 
00370   r = (*(bf + width - 1) + *(bf + width + 1)) >> 1;
00371   // correct:
00372   // g = (*(bf - 1) + *(bf + width) + *(bf + 1)) / 3;
00373   // faster:
00374   g = (*(bf -1) + *(bf +1)) >> 1;
00375   RGB2YUV(r, g, *bf, y2, u2, v2);
00376   ++bf;
00377 
00378   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00379 
00380   // rest of first line
00381   for (unsigned int w = 2; w < width - 2; w += 2) {
00382     b = (*(bf - 1) + *(bf + 1)) >> 1;
00383     RGB2YUV(*(bf + width), *bf, b, y1, u1, v1);
00384     ++bf;
00385 
00386     r = (*(bf + width - 1) + *(bf + width + 1)) >> 1;
00387     // correct:
00388     // g = (*(bf - 1) + *(bf + width) + *(bf + 1)) / 3;
00389     // faster:
00390     g = (*(bf - 1) + *(bf + 1)) >> 1;
00391     RGB2YUV(r, g, *bf, y2, u2, v2);
00392     ++bf;
00393 
00394     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00395   }
00396 
00397   // not full data in last columns
00398   b = (*(bf - 1) + *(bf + 1)) >> 1;
00399   RGB2YUV(*(bf + width), *bf, b, y1, u1, v1);
00400   ++bf;
00401 
00402   g = (*(bf - 1) + *(bf + width)) >> 1;
00403   RGB2YUV(*(bf + width - 1), g, *bf, y2, u2, v2);
00404   ++bf;
00405 
00406   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00407 
00408   for ( unsigned int h = 1; h < height - 1; h += 2) {
00409 
00410     // r  g  ... line
00411     // correct: g = (*(bf - width) + *(bf + 1) + *(bf + width)) / 3;
00412     // faster:
00413     g = (*(bf - width) + *(bf + 1)) >> 1;
00414     b = (*(bf + width - 1) + *(bf + width + 1)) >> 1;
00415     RGB2YUV(*bf, g, b, y1, u1, v1);
00416     ++bf;
00417 
00418     r = (*(bf - 1) + *(bf + 1)) >> 1;
00419     b = (*(bf - width) + *(bf + width)) >> 1;
00420     RGB2YUV(r, *bf, g, y2, u2, v2);
00421     ++bf;
00422 
00423     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00424 
00425     for (unsigned int w = 2; w < width - 2; w += 2) {
00426       g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
00427       b = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
00428       RGB2YUV(*bf, g, b, y1, u1, v1);
00429       ++bf;
00430 
00431       r = (*(bf - 1) + *(bf + 1)) >> 1;
00432       b = (*(bf - width) + *(bf + width)) >> 1;
00433       RGB2YUV(r, *bf, b, y2, u2, v2);
00434       ++bf;
00435 
00436       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00437     }
00438 
00439     g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
00440     b = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
00441     RGB2YUV(*bf, g, b, y1, u1, v1);
00442     ++bf;
00443 
00444     b = (*(bf - width) + *(bf + width)) >> 1;
00445     RGB2YUV(*(bf - 1), *bf, g, y2, u2, v2);
00446     ++bf;
00447 
00448     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00449 
00450 
00451 
00452     // g  b  ... line
00453     r = (*(bf + width) + *(bf - width)) >> 1;
00454     RGB2YUV(r, *bf, *(bf + 1), y1, u1, v1);
00455     ++bf;
00456 
00457     r = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
00458     g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
00459     RGB2YUV(r, g, *bf, y2, u2, v2);
00460     ++bf;
00461 
00462     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00463 
00464     for (unsigned int w = 2; w < width - 2; w += 2) {
00465       r = (*(bf + width) + *(bf - width)) >> 1;
00466       b = (*(bf - 1) + *(bf + 1)) >> 1;
00467       RGB2YUV(r, *bf, b, y1, u1, v1);
00468       ++bf;
00469 
00470       r = (*(bf - width - 1) + *(bf - width + 1) + *(bf + width - 1) + *(bf + width + 1)) >> 2;
00471       g = (*(bf - width) + *(bf + 1) + *(bf + width) + *(bf - 1)) >> 2;
00472       RGB2YUV(r, g, *bf, y2, u2, v2);
00473       ++bf;
00474 
00475       assign(y, u, v, y1, u1, v1, y2, u2, v2);
00476     }
00477 
00478     r = (*(bf + width) + *(bf - width)) >> 1;
00479     b = (*(bf - 1) + *(bf + 1)) >> 1;
00480     RGB2YUV(r, *bf, b, y1, u1, v1);
00481     ++bf;
00482 
00483     r = (*(bf - width - 1) + *(bf + width - 1)) >> 1;
00484     // correct: g = (*(bf - width) + *(bf + width) + *(bf - 1)) / 3;
00485     // faster:
00486     g = (*(bf - width) + *(bf - 1)) >> 1;
00487     RGB2YUV(r, g, *bf, y2, u2, v2);
00488     ++bf;
00489 
00490     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00491   }
00492 
00493   // last r  g  ... line
00494   // correct: g = (*(bf - width) + *(bf + 1) + *(bf + width)) / 3;
00495   // faster:
00496   g = (*(bf - width) + *(bf + 1)) >> 1;
00497   b = *(bf - width + 1);
00498   RGB2YUV(*bf, g, b, y1, u1, v1);
00499   ++bf;
00500 
00501   r = (*(bf - 1) + *(bf + 1)) >> 1;
00502   b = *(bf - width);
00503   RGB2YUV(r, g, *bf, y2, u2, v2);
00504   ++bf;
00505 
00506   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00507 
00508   for (unsigned int w = 2; w < width - 2; w += 2) {
00509     // correct: g = (*(bf - width) + *(bf + 1) + *(bf - 1)) / 3
00510     // faster:
00511     g = (*(bf - width) + *(bf - 1)) >> 1;
00512     b = (*(bf - width - 1) + *(bf - width + 1)) >> 1;
00513     RGB2YUV(*bf, g, b, y1, u1, v1);
00514     ++bf;
00515 
00516     r = (*(bf - 1) + *(bf + 1)) >> 1;
00517     b = *(bf - width);
00518     RGB2YUV(r, *bf, b, y2, u2, v2);
00519     ++bf;
00520 
00521     assign(y, u, v, y1, u1, v1, y2, u2, v2);
00522   }
00523 
00524   // correct: g = (*(bf - width) + *(bf + 1) + *(bf - 1)) / 3;
00525   // faster:
00526   g = (*(bf - width) + *(bf - 1)) >> 1;
00527   b = (*(bf - width - 1) + *(bf - width + 1)) >> 1;
00528   RGB2YUV(*bf, g, b, y1, u1, v1);
00529   ++bf;
00530 
00531   b = *(bf - width);
00532   RGB2YUV(*(bf - 1), *bf, b, y2, u2, v2);
00533   ++bf;
00534 
00535   assign(y, u, v, y1, u1, v1, y2, u2, v2);
00536 
00537 }
00538 */