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 namespace firevision {
00033 #if 0 /* just to make Emacs auto-indent happy */
00034 }
00035 #endif
00036 
00037 void
00038 rgb_to_yuy2(const unsigned char *RGB, unsigned char *YUV, unsigned int width, unsigned int height)
00039 {
00040   unsigned int i, j;
00041   register int y0, y1, u0, u1, v0, v1 ;
00042   register int r, g, b;
00043 
00044   for (i = 0, j = 0; i < 3 * width * height; i += 6, j += 4) {
00045     r = RGB[i + 0];
00046     g = RGB[i + 1];
00047     b = RGB[i + 2];
00048     RGB2YUV(r, g, b, y0, u0 , v0);
00049     r = RGB[i + 3];
00050     g = RGB[i + 4];
00051     b = RGB[i + 5];
00052     RGB2YUV(r, g, b, y1, u1 , v1);
00053     YUV[j + 0] = y0;
00054     YUV[j + 1] = (u0+u1)/2;
00055     YUV[j + 2] = y1;
00056     YUV[j + 3] = (v0+v1)/2;
00057   }
00058 }
00059 
00060 
00061 /** RGB to YUV Conversion
00062  *
00063  * Y  =      (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
00064  * Cr = V =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
00065  * Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
00066  *
00067  * Values have to be clamped to keep them in the [0-255] range.
00068  * Rumour has it that the valid range is actually a subset of [0-255] (fourcc.org mentions an RGB range
00069  * of [16-235]) but clamping the values into [0-255] seems to produce acceptable results.
00070  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00071  *            (thus this is a 24bit RGB with one byte per color) line by line.
00072  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00073  *            line
00074  * @param width Width of the image contained in the RGB buffer
00075  * @param height Height of the image contained in the RGB buffer
00076  */
00077 void
00078 rgb_to_yuv411packed_plainc(const unsigned char *RGB, unsigned char *YUV,
00079                            unsigned int width, unsigned int height)
00080 {
00081   register unsigned int i = 0, j = 0;
00082   register int y[4] = {0, 0, 0, 0}, u, v;
00083   register RGB_t *r;
00084   register unsigned int su = 0;
00085   register unsigned int sv = 0;
00086 
00087   while (i < (width * height)) {
00088     r = (RGB_t *)RGB;
00089     for (register unsigned int k = 0; j <= 4; ++j) {
00090       RGB2YUV(r->R, r->G, r->B, y[k], u, v);
00091       su += u;
00092       sv += v;
00093       RGB += 3;
00094     }
00095     YUV[j++] = su/4;
00096     YUV[j++] = y[0];
00097     YUV[j++] = y[1];
00098     YUV[j++] = sv/4;
00099     YUV[j++] = y[2];
00100     YUV[j++] = y[3];
00101   }
00102 }
00103 
00104 
00105 /** Convert a line of a RGB buffer to a line in a planar YUV422 buffer.
00106  * See above for general notes about color space conversion from RGB to YUV.
00107  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00108  *            (thus this is a 24bit RGB with one byte per color) line by line.
00109  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00110  *            line
00111  * @param width Width of the image contained in the RGB buffer
00112  * @param height Height of the image contained in the RGB buffer
00113  * @param rgb_line the index of the line to be converted
00114  * @param yuv_line the index of the line to convert to in the YUV buffer
00115  */
00116 void
00117 convert_line_rgb_to_yuv422planar(const unsigned char *RGB, unsigned char *YUV,
00118                                  unsigned int width, unsigned int height,
00119                                  unsigned int rgb_line, unsigned int yuv_line)
00120 {
00121   register unsigned int i = 0;
00122   register int y1, y2, u1, u2, v1, v2;
00123   register RGB_t *r1, *r2;
00124   register unsigned char *yp, *up, *vp;
00125 
00126   yp = YUV + (width * yuv_line);
00127   up = YUV422_PLANAR_U_PLANE(YUV, width, height) + (width * yuv_line / 2);
00128   vp = YUV422_PLANAR_V_PLANE(YUV, width, height) + (width * yuv_line / 2);
00129 
00130   RGB += 3 * width * rgb_line;
00131 
00132   while (i < width) {
00133     r1 = (RGB_t *)RGB;
00134     RGB += 3;
00135     r2 = (RGB_t *)RGB;
00136     RGB += 3;
00137 
00138     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00139     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00140 
00141     *yp++ = y1;
00142     *yp++ = y2;
00143     *up++ = (u1 + u2) / 2;
00144     *vp++ = (v1 + v2) / 2;
00145 
00146     i += 2;
00147   }
00148 }
00149 
00150 
00151 /** Convert an RGB buffer to a planar YUV422 buffer.
00152  * See above for general notes about color space conversion from RGB to YUV.
00153  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00154  *            (thus this is a 24bit RGB with one byte per color) line by line.
00155  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00156  *            line
00157  * @param width Width of the image contained in the RGB buffer
00158  * @param height Height of the image contained in the RGB buffer
00159  */
00160 void
00161 rgb_to_yuv422planar_plainc(const unsigned char *RGB, unsigned char *YUV,
00162                            unsigned int width, unsigned int height)
00163 {
00164   register unsigned int i = 0;
00165   register int y1, y2, u1, u2, v1, v2;
00166   register RGB_t *r1, *r2;
00167   register unsigned char *yp, *up, *vp;
00168 
00169   yp = YUV;
00170   up = YUV422_PLANAR_U_PLANE(YUV, width, height);
00171   vp = YUV422_PLANAR_V_PLANE(YUV, width, height);
00172 
00173   while (i < (width * height)) {
00174     r1 = (RGB_t *)RGB;
00175     RGB += 3;
00176     r2 = (RGB_t *)RGB;
00177     RGB += 3;
00178 
00179     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00180     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00181 
00182     *yp++ = y1;
00183     *yp++ = y2;
00184     *up++ = (u1 + u2) / 2;
00185     *vp++ = (v1 + v2) / 2;
00186 
00187     i += 2;
00188   }
00189 }
00190 
00191 /* Convert a line of a RGB buffer to a line in a packed YUV422 buffer, see above for general
00192  * notes about color space conversion from RGB to YUV
00193  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00194  *            (thus this is a 24bit RGB with one byte per color) line by line.
00195  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00196  *            line
00197  * @param width Width of the image contained in the RGB buffer
00198  * @param height Height of the image contained in the RGB buffer
00199  * @param rgb_line the index of the line to be converted
00200  * @param yuv_line the index of the line to convert to in the YUV buffer
00201  */
00202 void
00203 convert_line_rgb_to_yuv422packed(const unsigned char *RGB, unsigned char *YUV,
00204                                  unsigned int width, unsigned int height,
00205                                  unsigned int rgb_line, unsigned int yuv_line)
00206 {
00207   register unsigned int i = 0;
00208   register int y1, y2, u1, u2, v1, v2;
00209   register RGB_t *r1, *r2;
00210   register unsigned char *p;
00211 
00212   p = YUV + (width * yuv_line) * 2;
00213 
00214   RGB += 3 * width * rgb_line;
00215 
00216   while (i < width) {
00217     r1 = (RGB_t *)RGB;
00218     RGB += 3;
00219     r2 = (RGB_t *)RGB;
00220     RGB += 3;
00221 
00222     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00223     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00224 
00225     *p++ = (u1 + u2) / 2;
00226     *p++ = y1;
00227     *p++ = (v1 + v2) / 2;
00228     *p++ = y2;
00229 
00230     i += 2;
00231   }
00232 }
00233 
00234 /* Convert an RGB buffer to a packed YUV422 buffer, see above for general notes about color space
00235  * conversion from RGB to YUV
00236  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00237  *            (thus this is a 24bit RGB with one byte per color) line by line.
00238  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00239  *            line
00240  * @param width Width of the image contained in the RGB buffer
00241  * @param height Height of the image contained in the RGB buffer
00242  */
00243 void
00244 rgb_to_yuv422packed_plainc(const unsigned char *RGB, unsigned char *YUV,
00245                            unsigned int width, unsigned int height)
00246 {
00247   register unsigned int i = 0;
00248   register int y1, y2, u1, u2, v1, v2;
00249   register RGB_t *r1, *r2;
00250   register unsigned char *p;
00251 
00252   p = YUV;
00253 
00254   while (i < (width * height)) {
00255     r1 = (RGB_t *)RGB;
00256     RGB += 3;
00257     r2 = (RGB_t *)RGB;
00258     RGB += 3;
00259 
00260     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00261     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00262 
00263     *p++ = (u1 + u2) / 2;
00264     *p++ = y1;
00265     *p++ = (v1 + v2) / 2;
00266     *p++ = y2;
00267 
00268     i += 2;
00269   }
00270 }
00271 
00272 /** Convert an BGR buffer to a planar YUV422 buffer.
00273  * See above for general notes about color space conversion from RGB to YUV.
00274  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
00275  *            (thus this is a 24bit RGB with one byte per color) line by line.
00276  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
00277  *            line
00278  * @param width Width of the image contained in the RGB buffer
00279  * @param height Height of the image contained in the RGB buffer
00280  */
00281 void
00282 bgr_to_yuv422planar_plainc(const unsigned char *BGR, unsigned char *YUV,
00283                            unsigned int width, unsigned int height)
00284 {
00285   register unsigned int i = 0;
00286   register int y1, y2, u1, u2, v1, v2;
00287   register BGR_t *r1, *r2;
00288   register unsigned char *yp, *up, *vp;
00289 
00290   yp = YUV;
00291   up = YUV422_PLANAR_U_PLANE(YUV, width, height);
00292   vp = YUV422_PLANAR_V_PLANE(YUV, width, height);
00293 
00294   while (i < (width * height)) {
00295     r1 = (BGR_t *)BGR;
00296     BGR += 3;
00297     r2 = (BGR_t *)BGR;
00298     BGR += 3;
00299 
00300     RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
00301     RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
00302 
00303     *yp++ = y1;
00304     *yp++ = y2;
00305     *up++ = (u1 + u2) / 2;
00306     *vp++ = (v1 + v2) / 2;
00307 
00308     i += 2;
00309   }
00310 }
00311 
00312 } // end namespace firevision

Generated on Tue Feb 22 13:32:15 2011 for Fawkes API by  doxygen 1.4.7