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