rgbyuv.cpp

00001
00002 /****************************************************************************
00003  *  rgbyuv.h - RGB to YUV conversion - specific methods, macros and constants
00004  *
00005  *  Created: Sat Aug 12 15:21:39 2006
00006  *  based on colorspaces.h from Tue Feb 23 13:49:38 2005
00007  *  Copyright  2005-2006  Tim Niemueller [www.niemueller.de]
00008  *
00009  ****************************************************************************/
00010
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024
00025 #include <fvutils/color/rgbyuv.h>
00026 #include <fvutils/color/yuv.h>
00027 #include <fvutils/color/rgb.h>
00028 #include <fvutils/color/colorspaces.h>
00029
00030 #include <cstring>
00031
00032 void
00033 rgb_to_yuy2(const unsigned char *RGB, unsigned char *YUV, unsigned int width, unsigned int height)
00034 {
00035   unsigned int i, j;
00036   register int y0, y1, u0, u1, v0, v1 ;
00037   register int r, g, b;
00038
00039   for (i = 0, j = 0; i < 3 * width * height; i += 6, j += 4) {
00040     r = RGB[i + 0];
00041     g = RGB[i + 1];
00042     b = RGB[i + 2];
00043     RGB2YUV(r, g, b, y0, u0 , v0);
00044     r = RGB[i + 3];
00045     g = RGB[i + 4];
00046     b = RGB[i + 5];
00047     RGB2YUV(r, g, b, y1, u1 , v1);
00048     YUV[j + 0] = y0;
00049     YUV[j + 1] = (u0+u1)/2;
00050     YUV[j + 2] = y1;
00051     YUV[j + 3] = (v0+v1)/2;
00052   }
00053 }
00054
00055 
00056 /** RGB to YUV Conversion
00057  *
00058  * Y  =      (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
00059  * Cr = V =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
00060  * Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
00061  *
00062  * Values have to be clamped to keep them in the [0-255] range.
00063  * Rumour has it that the valid range is actually a subset of [0-255] (fourcc.org mentions an RGB range
00064  * of [16-235]) but clamping the values into [0-255] seems to produce acceptable results.
00065  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00066  *            (thus this is a 24bit RGB with one byte per color) line by line.
00067  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00068  *            line
00069  * @param width Width of the image contained in the RGB buffer
00070  * @param height Height of the image contained in the RGB buffer
00071  */
00072 void
00073 rgb_to_yuv411packed_plainc(const unsigned char *RGB, unsigned char *YUV,
00074                            unsigned int width, unsigned int height)
00075 {
00076   register unsigned int i = 0, j = 0;
00077   register int y[4] = {0, 0, 0, 0}, u, v;
00078   register RGB_t *r;
00079   register unsigned int su = 0;
00080   register unsigned int sv = 0;
00081
00082   while (i < (width * height)) {
00083     r = (RGB_t *)RGB;
00084     for (register unsigned int k = 0; j <= 4; ++j) {
00085       RGB2YUV(r->R, r->G, r->B, y[k], u, v);
00086       su += u;
00087       sv += v;
00088       RGB += 3;
00089     }
00090     YUV[j++] = su/4;
00091     YUV[j++] = y[0];
00092     YUV[j++] = y[1];
00093     YUV[j++] = sv/4;
00094     YUV[j++] = y[2];
00095     YUV[j++] = y[3];
00096   }
00097 }
00098
00099 
00100 /** Convert a line of a RGB buffer to a line in a planar YUV422 buffer.
00101  * See above for general notes about color space conversion from RGB to YUV.
00102  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00103  *            (thus this is a 24bit RGB with one byte per color) line by line.
00104  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00105  *            line
00106  * @param width Width of the image contained in the RGB buffer
00107  * @param height Height of the image contained in the RGB buffer
00108  * @param rgb_line the index of the line to be converted
00109  * @param yuv_line the index of the line to convert to in the YUV buffer
00110  */
00111 void
00112 convert_line_rgb_to_yuv422planar(const unsigned char *RGB, unsigned char *YUV,
00113                                  unsigned int width, unsigned int height,
00114                                  unsigned int rgb_line, unsigned int yuv_line)
00115 {
00116   register unsigned int i = 0;
00117   register int y1, y2, u1, u2, v1, v2;
00118   register RGB_t *r1, *r2;
00119   register unsigned char *yp, *up, *vp;
00120
00121   yp = YUV + (width * yuv_line);
00122   up = YUV422_PLANAR_U_PLANE(YUV, width, height) + (width * yuv_line / 2);
00123   vp = YUV422_PLANAR_V_PLANE(YUV, width, height) + (width * yuv_line / 2);
00124
00125   RGB += 3 * width * rgb_line;
00126
00127   while (i < width) {
00128     r1 = (RGB_t *)RGB;
00129     RGB += 3;
00130     r2 = (RGB_t *)RGB;
00131     RGB += 3;
00132
00133     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00134     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00135
00136     *yp++ = y1;
00137     *yp++ = y2;
00138     *up++ = (u1 + u2) / 2;
00139     *vp++ = (v1 + v2) / 2;
00140
00141     i += 2;
00142   }
00143 }
00144
00145 
00146 /** Convert an RGB buffer to a planar YUV422 buffer.
00147  * See above for general notes about color space conversion from RGB to YUV.
00148  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00149  *            (thus this is a 24bit RGB with one byte per color) line by line.
00150  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00151  *            line
00152  * @param width Width of the image contained in the RGB buffer
00153  * @param height Height of the image contained in the RGB buffer
00154  */
00155 void
00156 rgb_to_yuv422planar_plainc(const unsigned char *RGB, unsigned char *YUV,
00157                            unsigned int width, unsigned int height)
00158 {
00159   register unsigned int i = 0;
00160   register int y1, y2, u1, u2, v1, v2;
00161   register RGB_t *r1, *r2;
00162   register unsigned char *yp, *up, *vp;
00163
00164   yp = YUV;
00165   up = YUV422_PLANAR_U_PLANE(YUV, width, height);
00166   vp = YUV422_PLANAR_V_PLANE(YUV, width, height);
00167
00168   while (i < (width * height)) {
00169     r1 = (RGB_t *)RGB;
00170     RGB += 3;
00171     r2 = (RGB_t *)RGB;
00172     RGB += 3;
00173
00174     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00175     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00176
00177     *yp++ = y1;
00178     *yp++ = y2;
00179     *up++ = (u1 + u2) / 2;
00180     *vp++ = (v1 + v2) / 2;
00181
00182     i += 2;
00183   }
00184 }
00185
00186 /* Convert a line of a RGB buffer to a line in a packed YUV422 buffer, see above for general
00187  * notes about color space conversion from RGB to YUV
00188  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00189  *            (thus this is a 24bit RGB with one byte per color) line by line.
00190  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00191  *            line
00192  * @param width Width of the image contained in the RGB buffer
00193  * @param height Height of the image contained in the RGB buffer
00194  * @param rgb_line the index of the line to be converted
00195  * @param yuv_line the index of the line to convert to in the YUV buffer
00196  */
00197 void
00198 convert_line_rgb_to_yuv422packed(const unsigned char *RGB, unsigned char *YUV,
00199                                  unsigned int width, unsigned int height,
00200                                  unsigned int rgb_line, unsigned int yuv_line)
00201 {
00202   register unsigned int i = 0;
00203   register int y1, y2, u1, u2, v1, v2;
00204   register RGB_t *r1, *r2;
00205   register unsigned char *p;
00206
00207   p = YUV + (width * yuv_line) * 2;
00208
00209   RGB += 3 * width * rgb_line;
00210
00211   while (i < width) {
00212     r1 = (RGB_t *)RGB;
00213     RGB += 3;
00214     r2 = (RGB_t *)RGB;
00215     RGB += 3;
00216
00217     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00218     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00219
00220     *p++ = (u1 + u2) / 2;
00221     *p++ = y1;
00222     *p++ = (v1 + v2) / 2;
00223     *p++ = y2;
00224
00225     i += 2;
00226   }
00227 }
00228
00229 /* Convert an RGB buffer to a packed YUV422 buffer, see above for general notes about color space
00230  * conversion from RGB to YUV
00231  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00232  *            (thus this is a 24bit RGB with one byte per color) line by line.
00233  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00234  *            line
00235  * @param width Width of the image contained in the RGB buffer
00236  * @param height Height of the image contained in the RGB buffer
00237  */
00238 void
00239 rgb_to_yuv422packed_plainc(const unsigned char *RGB, unsigned char *YUV,
00240                            unsigned int width, unsigned int height)
00241 {
00242   register unsigned int i = 0;
00243   register int y1, y2, u1, u2, v1, v2;
00244   register RGB_t *r1, *r2;
00245   register unsigned char *p;
00246
00247   p = YUV;
00248
00249   while (i < (width * height)) {
00250     r1 = (RGB_t *)RGB;
00251     RGB += 3;
00252     r2 = (RGB_t *)RGB;
00253     RGB += 3;
00254
00255     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00256     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00257
00258     *p++ = (u1 + u2) / 2;
00259     *p++ = y1;
00260     *p++ = (v1 + v2) / 2;
00261     *p++ = y2;
00262
00263     i += 2;
00264   }
00265 }
00266 
00267 /** Convert an BGR buffer to a planar YUV422 buffer.
00268  * See above for general notes about color space conversion from RGB to YUV.
00269  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00270  *            (thus this is a 24bit RGB with one byte per color) line by line.
00271  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00272  *            line
00273  * @param width Width of the image contained in the RGB buffer
00274  * @param height Height of the image contained in the RGB buffer
00275  */
00276 void
00277 bgr_to_yuv422planar_plainc(const unsigned char *BGR, unsigned char *YUV,
00278                            unsigned int width, unsigned int height)
00279 {
00280   register unsigned int i = 0;
00281   register int y1, y2, u1, u2, v1, v2;
00282   register BGR_t *r1, *r2;
00283   register unsigned char *yp, *up, *vp;
00284
00285   yp = YUV;
00286   up = YUV422_PLANAR_U_PLANE(YUV, width, height);
00287   vp = YUV422_PLANAR_V_PLANE(YUV, width, height);
00288
00289   while (i < (width * height)) {
00290     r1 = (BGR_t *)BGR;
00291     BGR += 3;
00292     r2 = (BGR_t *)BGR;
00293     BGR += 3;
00294
00295     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00296     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00297
00298     *yp++ = y1;
00299     *yp++ = y2;
00300     *up++ = (u1 + u2) / 2;
00301     *vp++ = (v1 + v2) / 2;
00302
00303     i += 2;
00304   }
00305 }
00306