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