yuv.cpp

00001
00002 /***************************************************************************
00003  *  yuv.h - YUV specific methods, macros and constants
00004  *
00005  *  Created: Sat Aug 12 15:00:12 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/yuv.h>
00026 #include <fvutils/color/colorspaces.h>
00027 #include <cstring>
00028
00029 void
00030 iyu1_to_yuy2(const unsigned char *src, unsigned char *dest, unsigned int width, unsigned int height)
00031 {
00032   unsigned int i=0, j=0;
00033   register int y0, y1, y2, y3, u, v;
00034   while (i < width * height * 3 / 2) {
00035     u = src[i++];
00036     y0 = src[i++];
00037     y1 = src[i++];
00038     v = src[i++];
00039     y2 = src[i++];
00040     y3 = src[i++];
00041
00042     dest[j++] = y0;
00043     dest[j++] = u;
00044     dest[j++] = y1;
00045     dest[j++] = v;
00046
00047     dest[j++] = y2;
00048     dest[j++] = u;
00049     dest[j++] = y3;
00050     dest[j++] = v;
00051   }
00052 }
00053
00054 
00055 /** 8-Bit gray to YUY2 conversion
00056  * This function takes the gray value as Y and sets U and V to 128.
00057  */
00058 void
00059 gray8_to_yuy2(const unsigned char *src, unsigned char *dest, unsigned int width, unsigned int height)
00060 {
00061   register unsigned int i=0, j=0;
00062   while (i < width * height) {
00063     dest[j++] = src[i++];
00064     dest[j++] = 128;
00065     dest[j++] = src[i++];
00066     dest[j++] = 128;
00067   }
00068 }
00069
00070 
00071 /** 8-Bit gray to YUV422_PLANAR
00072  */
00073 void
00074 gray8_to_yuv422planar_plainc(const unsigned char *src, unsigned char *dst,
00075                              unsigned int width, unsigned int height)
00076 {
00077   // copy Y plane
00078   memcpy(dst, src, width * height);
00079   // set U and V plane
00080   memset(YUV422_PLANAR_U_PLANE(dst, width, height), 128, width * height);
00081 }
00082
00083
00084 
00085 /** Copy part of the U anv V planes of a YUV422planar image to another
00086  */
00087 void
00088 yuv422planar_copy_uv(const unsigned char *src, unsigned char *dst,
00089                      unsigned int width, unsigned int height,
00090                      unsigned int x, unsigned int y,
00091                      unsigned int copy_width, unsigned int copy_height)
00092 {
00093
00094   register const unsigned char *sup = YUV422_PLANAR_U_PLANE(src, width, height) + (x / 2);
00095   register const unsigned char *svp = YUV422_PLANAR_V_PLANE(src, width, height) + (x / 2);
00096
00097   register unsigned char *dup = YUV422_PLANAR_U_PLANE(dst, width, height) + (x / 2);
00098   register unsigned char *dvp = YUV422_PLANAR_V_PLANE(dst, width, height) + (x / 2);
00099
00100   register unsigned int w;
00101   register unsigned int h;
00102
00103   unsigned const char *lsup = sup, *lsvp = svp, *ldup = dup, *ldvp = dvp;
00104
00105   for (h = 0; h < copy_height; ++h) {
00106     for ( w = 0; w < copy_width; w += 2 ) {
00107       *dup++ = *sup++;
00108       *dvp++ = *svp++;
00109     }
00110     lsup += width / 2;
00111     lsvp += width / 2;
00112     ldup += width / 2;
00113     ldvp += width / 2;
00114   }
00115 }
00116
00117
00118 void
00119 yuv422planar_to_yuv422packed(const unsigned char *planar, unsigned char *packed,
00120                              unsigned int width, unsigned int height)
00121 {
00122   register const unsigned char *y, *u, *v;
00123   register unsigned int i;
00124
00125   y = planar;
00126   u = planar + (width * height);
00127   v = u + (width * height / 2);
00128
00129   for (i = 0; i < (width * height / 2); ++i) {
00130     *packed++ = *u++;
00131     *packed++ = *y++;
00132     *packed++ = *v++;
00133     *packed++ = *y++;
00134   }
00135 }
00136
00137 void
00138 yuv422planar_quarter_to_yuv422packed(const unsigned char *planar, unsigned char *packed,
00139                                      const unsigned int width,
00140                                      const unsigned int height)
00141 {
00142   volatile const unsigned char *y, *u, *v;
00143   register unsigned int w, h;
00144
00145   const unsigned int w_h_4 = (width * height) / 4;
00146   const unsigned int w_h_8 = (width * height) / 8;
00147   const unsigned int w_t_2   = width * 2;
00148   const unsigned int w_b_2   = width / 2;
00149   const unsigned int w_b_4   = width / 4;
00150
00151
00152   for (h = 0; h < height / 2; ++h) {
00153     y = planar + (h * w_b_2);
00154     u = planar + w_h_4 + (h * w_b_4);
00155     v = planar + w_h_4 + w_h_8 + (h * w_b_4);
00156
00157     for (w = 0; w < w_b_4; ++w) {
00158       packed[h * w_t_2 + w * 4    ] = *u++;
00159       packed[h * w_t_2 + w * 4 + 1] = *y++;
00160       packed[h * w_t_2 + w * 4 + 2] = *v++;
00161       packed[h * w_t_2 + w * 4 + 3] = *y++;
00162     }
00163   }
00164 }
00165
00166 void
00167 yuv422packed_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
00168                              unsigned int width, unsigned int height)
00169 {
00170   register volatile unsigned char *y, *u, *v;
00171   register int i, iy, iiy;
00172
00173   unsigned int wh = (width * height);
00174   int wh2 = wh >> 1;
00175   y = planar;
00176   u = planar + wh;
00177   v = u + wh2;
00178
00179 #ifdef _OPENMP
00180   #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
00181 #endif
00182   for (i = 0; i < wh2; ++i) {
00183     iy  = i << 1;
00184     iiy = iy << 1;
00185     u[i]    = packed[iiy];
00186     y[iy]   = packed[iiy + 1];
00187     v[i]    = packed[iiy + 2];
00188     y[iy+1] = packed[iiy + 3];
00189   }
00190 }
00191
00192
00193 void
00194 yuy2_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
00195                              unsigned int width, unsigned int height)
00196 {
00197   register volatile unsigned char *y, *u, *v;
00198   register int i, iy, iiy;
00199
00200   unsigned int wh = (width * height);
00201   int wh2 = wh >> 1;
00202   y = planar;
00203   u = planar + wh;
00204   v = u + wh2;
00205
00206 #ifdef _OPENMP
00207   #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
00208 #endif
00209   for (i = 0; i < wh2; ++i) {
00210     iy  = i << 1;
00211     iiy = iy << 1;
00212     y[iy]   = packed[iiy];
00213     u[i]    = packed[iiy + 1];
00214     y[iy+1] = packed[iiy + 2];
00215     v[i]    = packed[iiy + 3];
00216   }
00217 }
00218
00219
00220 void
00221 yvy2_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
00222                              unsigned int width, unsigned int height)
00223 {
00224   register volatile unsigned char *y, *u, *v;
00225   register int i, iy, iiy;
00226
00227   unsigned int wh = (width * height);
00228   int wh2 = wh >> 1;
00229   y = planar;
00230   u = planar + wh;
00231   v = u + wh2;
00232
00233 #ifdef _OPENMP
00234   #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
00235 #endif
00236   for (i = 0; i < wh2; ++i) {
00237     iy  = i << 1;
00238     iiy = iy << 1;
00239     y[iy]   = packed[iiy];
00240     v[i]    = packed[iiy + 1];
00241     y[iy+1] = packed[iiy + 2];
00242     u[i]    = packed[iiy + 3];
00243   }
00244 }
00245
00246
00247 void
00248 yuy2_to_yuv422planar_quarter(const unsigned char *packed, unsigned char *planar,
00249                              const unsigned int width, const unsigned int height)
00250 {
00251   register volatile unsigned char *y, *u, *v;
00252   register unsigned int h, w;
00253
00254   unsigned int wh = (width * height);
00255   y = planar;
00256   u = planar + (wh / 4);
00257   v = u + (wh / 8);
00258
00259   const unsigned int w_b_2 = width / 2;
00260   const unsigned int w_b_4 = width / 4;
00261   const unsigned int w_t_2 = width * 2;
00262   unsigned int packpix;
00263
00264   for (h = 0; h < height / 2; ++h) {
00265     for (w = 0; w < width; w += 4) {
00266       packpix = (h * w_t_2 + w) * 2;
00267       y[h * w_b_2 + w / 2    ] = (packed[packpix + 0] + packed[packpix + 2]) / 2;
00268       u[h * w_b_4 + w / 4    ] = (packed[packpix + 1] + packed[packpix + 5]) / 2;
00269       y[h * w_b_2 + w / 2 + 1] = (packed[packpix + 4] + packed[packpix + 6]) / 2;
00270       v[h * w_b_4 + w / 4    ] = (packed[packpix + 3] + packed[packpix + 7]) / 2;
00271     }
00272   }
00273 }
00274
00275
00276 void
00277 yuv444packed_to_yuv422planar(const unsigned char *yuv444, unsigned char *yuv422,
00278                              unsigned int width, unsigned int height)
00279 {
00280   register volatile unsigned char *y, *u, *v;
00281   register int i, iy, iiy;
00282
00283   unsigned int wh = (width * height);
00284   int wh2 = wh >> 1;
00285   y = yuv422;
00286   u = yuv422 + wh;
00287   v = u + wh2;
00288
00289 #ifdef ___OPENMP
00290   #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, yuv444) schedule(static)
00291 #endif
00292   for (i = 0; i < wh2; ++i) {
00293     iy  = i << 1;
00294     iiy = i * 6;
00295     y[iy]   = yuv444[iiy];
00296     y[iy+1] = yuv444[iiy + 3];
00297     u[i]    = (yuv444[iiy + 1] + yuv444[iiy + 4]) >> 1;
00298     v[i]    = (yuv444[iiy + 2] + yuv444[iiy + 5]) >> 1;
00299   }
00300 }
00301
00302
00303 void
00304 yuv444packed_to_yuv422packed(const unsigned char *yvu444, unsigned char *yuv422,
00305                              unsigned int width, unsigned int height)
00306 {
00307   register int i, iiy;
00308
00309   unsigned int wh = (width * height);
00310   int wh2 = wh >> 1;
00311
00312 #ifdef ___OPENMP
00313 #  pragma omp parallel for firstprivate(wh2) private(i, iiy) shared(yuv422, yvu444) schedule(static)
00314 #endif
00315   for (i = 0; i < wh2; i += 4) {
00316     iiy = i * 6;
00317     yuv422[i] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
00318     yuv422[i+1] = yvu444[iiy];
00319     yuv422[i+2]   = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
00320     yuv422[i+3] = yvu444[iiy + 3];
00321   }
00322 }
00323
00324
00325 void
00326 yvu444packed_to_yuv422planar(const unsigned char *yvu444, unsigned char *yuv422,
00327                              unsigned int width, unsigned int height)
00328 {
00329   register volatile unsigned char *y, *u, *v;
00330   register int i, iy, iiy;
00331
00332   unsigned int wh = (width * height);
00333   int wh2 = wh >> 1;
00334   y = yuv422;
00335   u = yuv422 + wh;
00336   v = u + wh2;
00337
00338 #ifdef ___OPENMP
00339 #  pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, yvu444) schedule(static)
00340 #endif
00341   for (i = 0; i < wh2; ++i) {
00342     iy  = i << 1;
00343     iiy = i * 6;
00344     y[iy]   = yvu444[iiy];
00345     y[iy+1] = yvu444[iiy + 3];
00346     u[i]    = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
00347     v[i]    = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
00348   }
00349 }
00350
00351
00352 void
00353 yvu444packed_to_yuv422packed(const unsigned char *yvu444, unsigned char *yuv422,
00354                              unsigned int width, unsigned int height)
00355 {
00356   register int i, iiy;
00357
00358   unsigned int wh = (width * height);
00359   int wh2 = wh >> 1;
00360
00361 #ifdef ___OPENMP
00362 #  pragma omp parallel for firstprivate(wh2) private(i, iiy) shared(yuv422, yvu444) schedule(static)
00363 #endif
00364   for (i = 0; i < wh2; i += 4) {
00365     iiy = i * 6;
00366     yuv422[i]   = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
00367     yuv422[i+1] = yvu444[iiy];
00368     yuv422[i+2] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
00369     yuv422[i+3] = yvu444[iiy + 3];
00370   }
00371 }
00372
00373
00374 void
00375 yuv422planar_erase_y_plane(unsigned char *yuv, unsigned int width, unsigned int height)
00376 {
00377   memset(yuv, 128, (width * height));
00378 }
00379
00380
00381 void
00382 yuv422planar_erase_u_plane(unsigned char *yuv, unsigned int width, unsigned int height)
00383 {
00384   memset(yuv + (width * height), 128, (width * height / 2));
00385 }
00386
00387
00388 void
00389 yuv422planar_erase_v_plane(unsigned char *yuv, unsigned int width, unsigned int height)
00390 {
00391   memset(yuv + (width * height * 3/2), 128, (width * height / 2));
00392 }
00393
00394
00395 void
00396 grayscale_yuv422packed(const unsigned char *src,   unsigned char *dst,
00397                        unsigned int   width, unsigned int   height)
00398 {
00399   unsigned int p = 0;
00400   unsigned int d = 0;
00401   while (p < colorspace_buffer_size(YUV422_PACKED, width, height)) {
00402     if ( (p % 2) == 0 ) {
00403       //dst[p] = 128;
00404     } else {
00405       dst[d++] = src[p];
00406     }
00407     p += 1;
00408   }
00409 }
00410
00411
00412 void
00413 grayscale_yuv422planar(const unsigned char *src, unsigned char *dst,
00414                        unsigned int width, unsigned int height)
00415 {
00416   memcpy(dst, src, width * height);
00417   memset(dst + width * height, 128, width * height);
00418 }
00419