Fawkes API  Fawkes Development Version
yuvrgb.h
00001 
00002 /****************************************************************************
00003  *  yuvrgb.h - YUV to RGB conversion - specific methods, macros and constants
00004  *
00005  *  Created: Sat Aug 12 15:01:36 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 #ifndef __FIREVISION_UTILS_COLOR_YUVRGB_H
00026 #define __FIREVISION_UTILS_COLOR_YUVRGB_H
00027 
00028 #include <fvutils/color/yuv.h>
00029 #include <fvutils/color/rgb.h>
00030 
00031 namespace firevision {
00032 #if 0 /* just to make Emacs auto-indent happy */
00033 }
00034 #endif
00035 
00036 
00037 #define YUV2RGB(y, u, v, r, g, b) {\
00038     r = y + ((v*1436) >> 10);                   \
00039     g = y - ((u*352 + v*731) >> 10);            \
00040     b = y + ((u*1814) >> 10);                   \
00041     r = r < 0 ? 0 : r;                          \
00042     g = g < 0 ? 0 : g;                          \
00043     b = b < 0 ? 0 : b;                          \
00044     r = r > 255 ? 255 : r;                      \
00045     g = g > 255 ? 255 : g;                      \
00046     b = b > 255 ? 255 : b; }
00047 
00048 
00049 #define clip(x) (unsigned char)( (x) < 0 ? 0 : ( (x) > 255 ? 255 : (x) ) )
00050 
00051 
00052 #define yuv411packed_to_rgb(YUV, RGB, width, height) yuv411packed_to_rgb_plainc(YUV, RGB, width, height)
00053 
00054 
00055 
00056 /** YUV to RGB Conversion
00057  * B = 1.164(Y - 16)                  + 2.018(U - 128)
00058  * G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
00059  * R = 1.164(Y - 16) + 1.596(V - 128)
00060  *
00061  * Values have to be clamped to keep them in the [0-255] range.
00062  * Rumour has it that the valid range is actually a subset of [0-255] (fourcc.org mentions an RGB range
00063  * of [16-235] mentioned) but clamping the values into [0-255] seems to produce acceptable results.
00064  * @param YUV unsigned char array that contains the pixels, 4 pixels in 6 byte macro pixel, line after
00065  *            line
00066  * @param RGB where the RGB output will be written to, will have pixel after pixel, 3 bytes per pixel
00067  *            (thus this is a 24bit RGB with one byte per color) line by line.
00068  * @param width Width of the image contained in the YUV buffer
00069  * @param height Height of the image contained in the YUV buffer
00070  */
00071 void yuv411packed_to_rgb_plainc(const unsigned char *YUV, unsigned char *RGB,
00072                                 unsigned int width, unsigned int height);
00073 
00074 
00075 /** YUV to RGB Conversion
00076  * B = 1.164(Y - 16)                  + 2.018(U - 128)
00077  * G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
00078  * R = 1.164(Y - 16) + 1.596(V - 128)
00079  *
00080  * Values have to be clamped to keep them in the [0-255] range.
00081  * Rumour has it that the valid range is actually a subset of [0-255] (fourcc.org mentions an RGB range
00082  * of [16-235] mentioned) but clamping the values into [0-255] seems to produce acceptable results.
00083  * @param YUV unsigned char array that contains the pixels, 4 pixels in 6 byte macro pixel, line after
00084  *            line
00085  * @param RGB where the RGB output will be written to, will have pixel after pixel, 3 bytes per pixel
00086  *            (thus this is a 24bit RGB with one byte per color) line by line.
00087  * @param width Width of the image contained in the YUV buffer
00088  * @param height Height of the image contained in the YUV buffer
00089  */
00090 void yuv422planar_to_rgb_plainc(const unsigned char *planar, unsigned char *RGB,
00091                                 unsigned int width, unsigned int height);
00092 
00093 void yuv422packed_to_rgb_plainc(const unsigned char *planar, unsigned char *RGB,
00094                                 unsigned int width, unsigned int height);
00095 
00096 void yuv422planar_to_bgr_plainc(const unsigned char *planar, unsigned char *BGR,
00097                                 unsigned int width, unsigned int height);
00098 
00099 
00100 void yuv422planar_to_rgb_with_alpha_plainc(const unsigned char *planar, unsigned char *RGB,
00101                                            unsigned int width, unsigned int height);
00102 
00103 void yuv422planar_to_bgr_with_alpha_plainc(const unsigned char *planar, unsigned char *BGR,
00104                                            unsigned int width, unsigned int height);
00105 
00106 void yuv422packed_to_bgr_with_alpha_plainc(const unsigned char *YUV, unsigned char *BGR,
00107                                            unsigned int width, unsigned int height);
00108 
00109 
00110 #if (defined __i386__ ||    \
00111      defined __386__ ||     \
00112      defined __X86__ ||     \
00113      defined _M_IX86 ||     \
00114      defined i386 )
00115 void yuv411planar_to_rgb_mmx (const unsigned char *yuv, unsigned char *rgb,
00116                               unsigned int w, unsigned int h);
00117 #endif
00118 
00119 
00120 
00121 inline void
00122 pixel_yuv_to_rgb(const unsigned char y, unsigned u, unsigned char v,
00123                  unsigned char *r, unsigned char *g, unsigned char *b)
00124 {
00125   int yt, ut, vt;
00126 
00127   yt = y - 16;
00128   ut = u - 128;
00129   vt = v - 128;
00130 
00131   *r = clip( (76284 * yt + 104595 * vt              ) >> 16 );
00132   *g = clip( (76284 * yt -  25625 * ut - 53281 * vt ) >> 16 );
00133   *b = clip( (76284 * yt + 132252 * ut              ) >> 16 );
00134 
00135 }
00136 
00137 
00138 /* Convert a line of a RGB buffer to a line in a planar YUV422 buffer, see above for general
00139  * notes about color space conversion from RGB to YUV
00140  * @param RGB where the RGB output will be written to, will have pixel after pixel, 3 bytes per pixel
00141  *            (thus this is a 24bit RGB with one byte per color) line by line.
00142  * @param YUV unsigned char array that contains the pixels, 4 pixels in 6 byte macro pixel, line after
00143  *            line
00144  * @param width Width of the image contained in the YUV buffer
00145  * @param height Height of the image contained in the YUV buffer
00146  * @param rgb_line the index of the line to be converted
00147  * @param yuv_line the index of the line to convert to in the YUV buffer
00148  */
00149 inline void
00150 convert_line_yuv422planar_to_rgb(const unsigned char *YUV, unsigned char *RGB,
00151                                  unsigned int width, unsigned int height,
00152                                  unsigned int yuv_line, unsigned int rgb_line)
00153 {
00154   register unsigned int i = 0;
00155   register RGB_t *r1, *r2;
00156   register const unsigned char *yp, *up, *vp;
00157 
00158   yp = YUV + (width * yuv_line);
00159   up = YUV422_PLANAR_U_PLANE(YUV, width, height) + (width * yuv_line / 2);
00160   vp = YUV422_PLANAR_V_PLANE(YUV, width, height) + (width * yuv_line / 2);
00161 
00162   RGB += 3 * width * rgb_line;
00163 
00164   while (i < width) {
00165     r1 = (RGB_t *)RGB;
00166     RGB += 3;
00167     r2 = (RGB_t *)RGB;
00168     RGB += 3;
00169 
00170     pixel_yuv_to_rgb(*yp++, *up, *vp, &(r1->R), &(r1->G), &(r1->B));
00171     pixel_yuv_to_rgb(*yp++, *up++, *vp++, &(r2->R), &(r2->G), &(r2->B));
00172 
00173     i += 2;
00174   }
00175 }
00176 
00177 } // end namespace firevision
00178 
00179 #endif