Fawkes API
Fawkes Development Version
|
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