color_conversions.C
Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include "Image/color_conversions.H"
00039 
00040 #include "Image/Image.H"
00041 #include "Image/Pixels.H"
00042 #include "Image/colorDefs.H"  
00043 #include "Util/Promotions.H" 
00044 #include "rutz/trace.h"
00045 
00046 #include <pthread.h>
00047 
00048 namespace
00049 {
00050   
00051   
00052   const int BITS_OUT = 16;
00053 
00054   
00055 
00056   int RGB_Y_tab[256];
00057   int B_U_tab[256];
00058   int G_U_tab[256];
00059   int G_V_tab[256];
00060   int R_V_tab[256];
00061 
00062   pthread_once_t colorspace_init_once = PTHREAD_ONCE_INIT;
00063 
00064   void colorspace_init()
00065   {
00066     
00067     const int half =
00068       BITS_OUT > 0
00069       ? 1<<(BITS_OUT-1)
00070       : 0;
00071 
00072     const int scale = 1<<BITS_OUT;
00073 
00074     for (int i = 0; i < 256; i++)
00075       {
00076         const int y  = i-VIDEOYUV_Y_OFFSET;
00077         const int uv = i-VIDEOYUV_UV_OFFSET;
00078 
00079         RGB_Y_tab[i] = half+int(0.5 + y  * VIDEOYUV_RGB_Y * scale);
00080         R_V_tab[i]   =      int(0.5 + uv * VIDEOYUV_R_V   * scale);
00081         
00082         
00083         G_U_tab[i]   =      int(0.5 - uv * VIDEOYUV_G_U   * scale);
00084         G_V_tab[i]   =      int(0.5 - uv * VIDEOYUV_G_V   * scale);
00085         B_U_tab[i]   =      int(0.5 + uv * VIDEOYUV_B_U   * scale);
00086       }
00087   }
00088 }
00089 
00090 void yv12_to_rgb24_c(unsigned char* dst,
00091                      int dst_stride,
00092                      const unsigned char* y_src,
00093                      const unsigned char* u_src,
00094                      const unsigned char* v_src,
00095                      int y_stride,
00096                      int uv_stride,
00097                      int width,
00098                      int height)
00099 {
00100 GVX_TRACE(__PRETTY_FUNCTION__);
00101 
00102   if (width & 1)
00103     LFATAL("width must be even");
00104 
00105   if (height & 1)
00106     LFATAL("height must be even");
00107 
00108   pthread_once(&colorspace_init_once, &colorspace_init);
00109 
00110   const int dst_dif = 6 * dst_stride - 3 * width;
00111   int y_dif = 2 * y_stride - width;
00112 
00113   unsigned char* dst2 = dst + 3 * dst_stride;
00114   const unsigned char* y_src2 = y_src + y_stride;
00115 
00116   if (height < 0) {                     
00117     height = -height;
00118     y_src += (height - 1) * y_stride;
00119     y_src2 = y_src - y_stride;
00120     u_src += (height / 2 - 1) * uv_stride;
00121     v_src += (height / 2 - 1) * uv_stride;
00122     y_dif = -width - 2 * y_stride;
00123     uv_stride = -uv_stride;
00124   }
00125 
00126   for (int y = height / 2; y; y--) {
00127     for (int x = 0; x < width / 2; x++) {
00128       const int u = u_src[x];
00129       const int v = v_src[x];
00130 
00131       const int r_v = R_V_tab[v];
00132       const int g_uv = - G_U_tab[u] - G_V_tab[v];
00133       const int b_u = B_U_tab[u];
00134 
00135       {
00136         const int rgb_y = RGB_Y_tab[*y_src];
00137         const int r = (rgb_y + r_v) >> BITS_OUT;
00138         const int g = (rgb_y + g_uv) >> BITS_OUT;
00139         const int b = (rgb_y + b_u) >> BITS_OUT;
00140         dst[0] = clamped_convert<unsigned char>(r);
00141         dst[1] = clamped_convert<unsigned char>(g);
00142         dst[2] = clamped_convert<unsigned char>(b);
00143         y_src++;
00144       }
00145       {
00146         const int rgb_y = RGB_Y_tab[*y_src];
00147         const int r = (rgb_y + r_v) >> BITS_OUT;
00148         const int g = (rgb_y + g_uv) >> BITS_OUT;
00149         const int b = (rgb_y + b_u) >> BITS_OUT;
00150         dst[3] = clamped_convert<unsigned char>(r);
00151         dst[4] = clamped_convert<unsigned char>(g);
00152         dst[5] = clamped_convert<unsigned char>(b);
00153         y_src++;
00154       }
00155       {
00156         const int rgb_y = RGB_Y_tab[*y_src2];
00157         const int r = (rgb_y + r_v) >> BITS_OUT;
00158         const int g = (rgb_y + g_uv) >> BITS_OUT;
00159         const int b = (rgb_y + b_u) >> BITS_OUT;
00160         dst2[0] = clamped_convert<unsigned char>(r);
00161         dst2[1] = clamped_convert<unsigned char>(g);
00162         dst2[2] = clamped_convert<unsigned char>(b);
00163         y_src2++;
00164       }
00165       {
00166         const int rgb_y = RGB_Y_tab[*y_src2];
00167         const int r = (rgb_y + r_v) >> BITS_OUT;
00168         const int g = (rgb_y + g_uv) >> BITS_OUT;
00169         const int b = (rgb_y + b_u) >> BITS_OUT;
00170         dst2[3] = clamped_convert<unsigned char>(r);
00171         dst2[4] = clamped_convert<unsigned char>(g);
00172         dst2[5] = clamped_convert<unsigned char>(b);
00173         y_src2++;
00174       }
00175 
00176       dst += 6;
00177       dst2 += 6;
00178     }
00179 
00180     dst += dst_dif;
00181     dst2 += dst_dif;
00182 
00183     y_src += y_dif;
00184     y_src2 += y_dif;
00185 
00186     u_src += uv_stride;
00187     v_src += uv_stride;
00188   }
00189 }
00190 
00191 
00192 
00193 
00194 
00195 
00196 #define Y_R_IN   0.257 // VIDEOYUV_Y_R from Image/colorDefs.H
00197 #define Y_G_IN   0.504 // VIDEOYUV_Y_G
00198 #define Y_B_IN   0.098 // VIDEOYUV_Y_B
00199 #define Y_ADD_IN 16
00200 
00201 #define U_R_IN   0.148 // -VIDEOYUV_U_R
00202 #define U_G_IN   0.291 // -VIDEOYUV_U_G
00203 #define U_B_IN   0.439 // VIDEOYUV_U_B
00204 #define U_ADD_IN 128
00205 
00206 #define V_R_IN   0.439 // VIDEOYUV_V_R
00207 #define V_G_IN   0.368 // -VIDEOYUV_V_G
00208 #define V_B_IN   0.071 // -VIDEOYUV_V_B
00209 #define V_ADD_IN 128
00210 
00211 #define SCALEBITS_IN 8
00212 
00213 #define FIX_IN(x) (int((x) * (1L<<SCALEBITS_IN) + 0.5))
00214 
00215 void rgb24_to_yv12_c(const Image<PixRGB<byte> >& img,
00216                      byte* const y_out,
00217                      byte* u_out,
00218                      byte* v_out)
00219 {
00220 GVX_TRACE(__PRETTY_FUNCTION__);
00221 
00222   const int width = img.getWidth();
00223   const int height = img.getHeight();
00224 
00225   const int width2 = width/2;
00226   const int height2 = height/2;
00227 
00228   typedef Image<PixRGB<byte> >::const_iterator src_iterator;
00229 
00230   const src_iterator in_begin = img.begin();
00231 
00232   for (int y = 0; y < height2; ++y)
00233     {
00234       
00235       
00236 
00237       src_iterator src1 = in_begin + 2 * y * width;
00238       src_iterator src2 = src1 + width;
00239 
00240       byte* y_out1 = y_out + 2 * y * width;
00241       byte* y_out2 = y_out1 + width;
00242 
00243       for (int x = 0; x < width2; ++x)
00244         {
00245           uint r, g, b, r4, g4, b4;
00246 
00247           r4 = r = src1->red();
00248           g4 = g = src1->green();
00249           b4 = b = src1->blue();
00250           ++src1;
00251           *y_out1++ =
00252             (byte) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +
00253                      FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
00254 
00255           r4 += (r = src1->red());
00256           g4 += (g = src1->green());
00257           b4 += (b = src1->blue());
00258           ++src1;
00259           *y_out1++ =
00260             (byte) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +
00261                      FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
00262 
00263           r4 += (r = src2->red());
00264           g4 += (g = src2->green());
00265           b4 += (b = src2->blue());
00266           ++src2;
00267           *y_out2++ =
00268             (byte) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +
00269                      FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
00270 
00271           r4 += (r = src2->red());
00272           g4 += (g = src2->green());
00273           b4 += (b = src2->blue());
00274           ++src2;
00275           *y_out2++ =
00276             (byte) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +
00277                      FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
00278 
00279           *u_out++ =
00280             (byte) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 +
00281                      FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) +
00282             U_ADD_IN;
00283 
00284 
00285           *v_out++ =
00286             (byte) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 -
00287                      FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) +
00288             V_ADD_IN;
00289 
00290 
00291           if (x==(width2-1) && (width&1))
00292             {
00293               r4 = r = src1->red();
00294               g4 = g = src1->green();
00295               b4 = b = src1->blue();
00296               ++src1;
00297               *y_out1++ =
00298                 (byte) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +
00299                          FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
00300 
00301               r4 += (r = src2->red());
00302               g4 += (g = src2->green());
00303               b4 += (b = src2->blue());
00304               ++src2;
00305               *y_out2++ =
00306                 (byte) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g +
00307                          FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
00308 
00309               *u_out++ =
00310                 (byte) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 +
00311                          FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 1)) +
00312                 U_ADD_IN;
00313 
00314               *v_out++ =
00315                 (byte) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 -
00316                          FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 1)) +
00317                 V_ADD_IN;
00318             }
00319         }
00320     }
00321 }
00322 
00323 void yuv422p_to_rgb24_c(byte* dst,
00324                         const int w, const int h,
00325                         const byte* yptr,
00326                         const byte* uptr,
00327                         const byte* vptr)
00328 {
00329   pthread_once(&colorspace_init_once, &colorspace_init);
00330 
00331   for (int j = 0; j < h; ++j)
00332     for (int i = 0; i < w; i += 2)
00333       {
00334         
00335 
00336         const int r_v = R_V_tab[*vptr];
00337         const int g_uv = - G_U_tab[*uptr] - G_V_tab[*vptr];
00338         const int b_u = B_U_tab[*uptr];
00339 
00340         ++uptr;
00341         ++vptr;
00342 
00343         
00344 
00345         {
00346           const int rgb_y1 = RGB_Y_tab[*yptr++];
00347 
00348           const int r1 = (rgb_y1 + r_v) >> BITS_OUT;
00349           const int g1 = (rgb_y1 + g_uv) >> BITS_OUT;
00350           const int b1 = (rgb_y1 + b_u) >> BITS_OUT;
00351 
00352           *dst++ = clamped_convert<byte>(r1);
00353           *dst++ = clamped_convert<byte>(g1);
00354           *dst++ = clamped_convert<byte>(b1);
00355 
00356         }
00357 
00358         
00359 
00360         {
00361           const int rgb_y2 = RGB_Y_tab[*yptr++];
00362 
00363           const int r2 = (rgb_y2 + r_v) >> BITS_OUT;
00364           const int g2 = (rgb_y2 + g_uv) >> BITS_OUT;
00365           const int b2 = (rgb_y2 + b_u) >> BITS_OUT;
00366 
00367           *dst++ = clamped_convert<byte>(r2);
00368           *dst++ = clamped_convert<byte>(g2);
00369           *dst++ = clamped_convert<byte>(b2);
00370         }
00371       }
00372 }
00373 
00374 void yuv422_to_rgb24_c(byte* dst,
00375                        const int w, const int h,
00376                        const byte* yuv422ptr,
00377                        const bool byteswap)
00378 {
00379   pthread_once(&colorspace_init_once, &colorspace_init);
00380 
00381   if (byteswap)
00382     for (int j = 0; j < h; ++j)
00383       for (int i = 0; i < w; i += 2)
00384         {
00385           
00386 
00387           const byte y1 = yuv422ptr[0];
00388           const byte u = yuv422ptr[1];
00389           const byte y2 = yuv422ptr[2];
00390           const byte v = yuv422ptr[3];
00391 
00392           yuv422ptr += 4;
00393 
00394           const int r_v = R_V_tab[v];
00395           const int g_uv = - G_U_tab[u] - G_V_tab[v];
00396           const int b_u = B_U_tab[u];
00397 
00398           
00399           const int rgb_y1 = RGB_Y_tab[y1];
00400 
00401           *dst++ = clamped_convert<byte>((rgb_y1 + r_v) >> BITS_OUT);
00402           *dst++ = clamped_convert<byte>((rgb_y1 + g_uv) >> BITS_OUT);
00403           *dst++ = clamped_convert<byte>((rgb_y1 + b_u) >> BITS_OUT);
00404 
00405           
00406           const int rgb_y2 = RGB_Y_tab[y2];
00407 
00408           *dst++ = clamped_convert<byte>((rgb_y2 + r_v) >> BITS_OUT);
00409           *dst++ = clamped_convert<byte>((rgb_y2 + g_uv) >> BITS_OUT);
00410           *dst++ = clamped_convert<byte>((rgb_y2 + b_u) >> BITS_OUT);
00411         }
00412 
00413   else 
00414     for (int j = 0; j < h; ++j)
00415       for (int i = 0; i < w; i += 2)
00416         {
00417           
00418 
00419           const byte y1 = yuv422ptr[1];
00420           const byte u = yuv422ptr[0];
00421           const byte y2 = yuv422ptr[3];
00422           const byte v = yuv422ptr[2];
00423 
00424           yuv422ptr += 4;
00425 
00426           const int r_v = R_V_tab[v];
00427           const int g_uv = - G_U_tab[u] - G_V_tab[v];
00428           const int b_u = B_U_tab[u];
00429 
00430           
00431           const int rgb_y1 = RGB_Y_tab[y1];
00432 
00433           *dst++ = clamped_convert<byte>((rgb_y1 + r_v) >> BITS_OUT);
00434           *dst++ = clamped_convert<byte>((rgb_y1 + g_uv) >> BITS_OUT);
00435           *dst++ = clamped_convert<byte>((rgb_y1 + b_u) >> BITS_OUT);
00436 
00437           
00438           const int rgb_y2 = RGB_Y_tab[y2];
00439 
00440           *dst++ = clamped_convert<byte>((rgb_y2 + r_v) >> BITS_OUT);
00441           *dst++ = clamped_convert<byte>((rgb_y2 + g_uv) >> BITS_OUT);
00442           *dst++ = clamped_convert<byte>((rgb_y2 + b_u) >> BITS_OUT);
00443         }
00444 }
00445 
00446 
00447 
00448 
00449 
00450