Fawkes API  Fawkes Development Version
yuv.cpp
1 
2 /***************************************************************************
3  * yuv.h - YUV specific methods, macros and constants
4  *
5  * Created: Sat Aug 12 15:00:12 2006
6  * based on colorspaces.h from Tue Feb 23 13:49:38 2005
7  * Copyright 2005-2006 Tim Niemueller [www.niemueller.de]
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version. A runtime exception applies to
15  * this software (see LICENSE.GPL_WRE file mentioned below for details).
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Library General Public License for more details.
21  *
22  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23  */
24 
25 #include <fvutils/color/yuv.h>
26 #include <fvutils/color/colorspaces.h>
27 #include <cstring>
28 
29 namespace firevision {
30 #if 0 /* just to make Emacs auto-indent happy */
31 }
32 #endif
33 
34 void
35 iyu1_to_yuy2(const unsigned char *src, unsigned char *dest, unsigned int width, unsigned int height)
36 {
37  unsigned int i=0, j=0;
38  int y0, y1, y2, y3, u, v;
39  while (i < width * height * 3 / 2) {
40  u = src[i++];
41  y0 = src[i++];
42  y1 = src[i++];
43  v = src[i++];
44  y2 = src[i++];
45  y3 = src[i++];
46 
47  dest[j++] = y0;
48  dest[j++] = u;
49  dest[j++] = y1;
50  dest[j++] = v;
51 
52  dest[j++] = y2;
53  dest[j++] = u;
54  dest[j++] = y3;
55  dest[j++] = v;
56  }
57 }
58 
59 
60 /** 8-Bit gray to YUY2 conversion
61  * This function takes the gray value as Y and sets U and V to 128.
62  */
63 void
64 gray8_to_yuy2(const unsigned char *src, unsigned char *dest, unsigned int width, unsigned int height)
65 {
66  unsigned int i=0, j=0;
67  while (i < width * height) {
68  dest[j++] = src[i++];
69  dest[j++] = 128;
70  dest[j++] = src[i++];
71  dest[j++] = 128;
72  }
73 }
74 
75 
76 /** 8-Bit gray to YUV422_PLANAR
77  */
78 void
79 gray8_to_yuv422planar_plainc(const unsigned char *src, unsigned char *dst,
80  unsigned int width, unsigned int height)
81 {
82  // copy Y plane
83  memcpy(dst, src, width * height);
84  // set U and V plane
85  memset(YUV422_PLANAR_U_PLANE(dst, width, height), 128, width * height);
86 }
87 
88 /** 8-Bit gray to YUV422_PACKED
89  */
90 void
91 gray8_to_yuv422packed_plainc(const unsigned char *src, unsigned char *dst,
92  unsigned int width, unsigned int height)
93 {
94  unsigned int i=0, j=0;
95  while (i < width * height) {
96  dst[j++] = 128;
97  dst[j++] = src[i++];
98  dst[j++] = 128;
99  dst[j++] = src[i++];
100  }
101 }
102 
103 
104 
105 /** Copy part of the U anv V planes of a YUV422planar image to another
106  */
107 void
108 yuv422planar_copy_uv(const unsigned char *src, unsigned char *dst,
109  unsigned int width, unsigned int height,
110  unsigned int x, unsigned int y,
111  unsigned int copy_width, unsigned int copy_height)
112 {
113 
114  const unsigned char *sup = YUV422_PLANAR_U_PLANE(src, width, height) + (x / 2);
115  const unsigned char *svp = YUV422_PLANAR_V_PLANE(src, width, height) + (x / 2);
116 
117  unsigned char *dup = YUV422_PLANAR_U_PLANE(dst, width, height) + (x / 2);
118  unsigned char *dvp = YUV422_PLANAR_V_PLANE(dst, width, height) + (x / 2);
119 
120  unsigned int w;
121  unsigned int h;
122 
123  unsigned const char *lsup = sup, *lsvp = svp, *ldup = dup, *ldvp = dvp;
124 
125  for (h = 0; h < copy_height; ++h) {
126  for ( w = 0; w < copy_width; w += 2 ) {
127  *dup++ = *sup++;
128  *dvp++ = *svp++;
129  }
130  lsup += width / 2;
131  lsvp += width / 2;
132  ldup += width / 2;
133  ldvp += width / 2;
134  }
135 }
136 
137 
138 /** Copy part of the U anv V planes of a YUV422planar image to another
139  */
140 void
141 yuv420planar_to_yuv422planar(const unsigned char *src, unsigned char *dst,
142  unsigned int width, unsigned int height)
143 {
144  const unsigned char *sup = YUV420_PLANAR_U_PLANE(src, width, height);
145  const unsigned char *svp = YUV420_PLANAR_V_PLANE(src, width, height);
146 
147  unsigned char *dup = YUV422_PLANAR_U_PLANE(dst, width, height);
148  unsigned char *dvp = YUV422_PLANAR_V_PLANE(dst, width, height);
149 
150  unsigned int h;
151 
152  // cp Y plane
153  memcpy(dst, src, width * height);
154 
155  for (h = 0; h < height / 2; ++h) {
156  // cp U line twice!
157  memcpy(dup, sup, width / 2);
158  dup += width / 2;
159  memcpy(dup, sup, width / 2);
160  dup += width / 2;
161  sup += width / 2;
162 
163  // cp V line twice!
164  memcpy(dvp, svp, width / 2);
165  dvp += width / 2;
166  memcpy(dvp, svp, width / 2);
167  dvp += width / 2;
168  svp += width / 2;
169  }
170 }
171 
172 
173 void
174 yuv422planar_to_yuv422packed(const unsigned char *planar, unsigned char *packed,
175  unsigned int width, unsigned int height)
176 {
177  const unsigned char *y, *u, *v;
178  unsigned int i;
179 
180  y = planar;
181  u = planar + (width * height);
182  v = u + (width * height / 2);
183 
184  for (i = 0; i < (width * height / 2); ++i) {
185  *packed++ = *u++;
186  *packed++ = *y++;
187  *packed++ = *v++;
188  *packed++ = *y++;
189  }
190 }
191 
192 void
193 yuv422planar_quarter_to_yuv422packed(const unsigned char *planar, unsigned char *packed,
194  const unsigned int width,
195  const unsigned int height)
196 {
197  volatile const unsigned char *y, *u, *v;
198  unsigned int w, h;
199 
200  const unsigned int w_h_4 = (width * height) / 4;
201  const unsigned int w_h_8 = (width * height) / 8;
202  const unsigned int w_t_2 = width * 2;
203  const unsigned int w_b_2 = width / 2;
204  const unsigned int w_b_4 = width / 4;
205 
206 
207  for (h = 0; h < height / 2; ++h) {
208  y = planar + (h * w_b_2);
209  u = planar + w_h_4 + (h * w_b_4);
210  v = planar + w_h_4 + w_h_8 + (h * w_b_4);
211 
212  for (w = 0; w < w_b_4; ++w) {
213  packed[h * w_t_2 + w * 4 ] = *u++;
214  packed[h * w_t_2 + w * 4 + 1] = *y++;
215  packed[h * w_t_2 + w * 4 + 2] = *v++;
216  packed[h * w_t_2 + w * 4 + 3] = *y++;
217  }
218  }
219 }
220 
221 
222 /* Convert quarter YUV422 planar buffer to plain YUV422 planar.
223  * @param quarter input buffer in YUV422_PLANAR_QUARTER
224  * @param output buffer in YUV422_PLANAR
225  * @param width width of the image (width of YUV422_PLANAR image)
226  * @param height height of the image (height of YUV422_PLANAR image)
227  */
228 void
229 yuv422planar_quarter_to_yuv422planar(const unsigned char *quarter,
230  unsigned char *planar,
231  const unsigned int width,
232  const unsigned int height)
233 {
234  volatile const unsigned char *y, *u, *v;
235  unsigned int w, h;
236 
237  const unsigned int w_h_4 = (width * height) / 4;
238  const unsigned int w_h_8 = (width * height) / 8;
239  //const unsigned int w_t_2 = width * 2;
240  const unsigned int w_b_2 = width / 2;
241  const unsigned int w_b_4 = width / 4;
242 
243  unsigned char *yp, *up, *vp, t;
244  yp = planar;
245  up = YUV422_PLANAR_U_PLANE(planar, width, height);
246  vp = YUV422_PLANAR_V_PLANE(planar, width, height);
247 
248  for (h = 0; h < height / 2; ++h) {
249  y = quarter + (h * w_b_2);
250  u = quarter + w_h_4 + (h * w_b_4);
251  v = quarter + w_h_4 + w_h_8 + (h * w_b_4);
252 
253  for (w = 0; w < w_b_4; ++w) {
254  t = *y++;
255  *yp++ = t;
256  *yp++ = t;
257  t = *y++;
258  *yp++ = t;
259  *yp++ = t;
260  t = *u++;
261  *up++ = t;
262  *up++ = t;
263  t = *v++;
264  *vp++ = t;
265  *vp++ = t;
266  }
267 
268  memcpy(yp, yp - width, width);
269  memcpy(up, up - w_b_2, w_b_2);
270  memcpy(vp, vp - w_b_2, w_b_2);
271  yp += width;
272  up += w_b_2;
273  vp += w_b_2;
274  }
275 
276 }
277 
278 void
279 yuv422packed_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
280  unsigned int width, unsigned int height)
281 {
282  volatile unsigned char *y, *u, *v;
283  int i, iy, iiy;
284 
285  unsigned int wh = (width * height);
286  int wh2 = wh >> 1;
287  y = planar;
288  u = planar + wh;
289  v = u + wh2;
290 
291 #ifdef _OPENMP
292  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
293 #endif
294  for (i = 0; i < wh2; ++i) {
295  iy = i << 1;
296  iiy = iy << 1;
297  u[i] = packed[iiy];
298  y[iy] = packed[iiy + 1];
299  v[i] = packed[iiy + 2];
300  y[iy+1] = packed[iiy + 3];
301  }
302 }
303 
304 
305 void
306 yuy2_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
307  unsigned int width, unsigned int height)
308 {
309  volatile unsigned char *y, *u, *v;
310  int i, iy, iiy;
311 
312  unsigned int wh = (width * height);
313  int wh2 = wh >> 1;
314  y = planar;
315  u = planar + wh;
316  v = u + wh2;
317 
318 #ifdef _OPENMP
319  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
320 #endif
321  for (i = 0; i < wh2; ++i) {
322  iy = i << 1;
323  iiy = iy << 1;
324  y[iy] = packed[iiy];
325  u[i] = packed[iiy + 1];
326  y[iy+1] = packed[iiy + 2];
327  v[i] = packed[iiy + 3];
328  }
329 }
330 
331 
332 void
333 yvy2_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
334  unsigned int width, unsigned int height)
335 {
336  volatile unsigned char *y, *u, *v;
337  int i, iy, iiy;
338 
339  unsigned int wh = (width * height);
340  int wh2 = wh >> 1;
341  y = planar;
342  u = planar + wh;
343  v = u + wh2;
344 
345 #ifdef _OPENMP
346  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
347 #endif
348  for (i = 0; i < wh2; ++i) {
349  iy = i << 1;
350  iiy = iy << 1;
351  y[iy] = packed[iiy];
352  v[i] = packed[iiy + 1];
353  y[iy+1] = packed[iiy + 2];
354  u[i] = packed[iiy + 3];
355  }
356 }
357 
358 
359 void
360 yuy2_to_yuv422planar_quarter(const unsigned char *packed, unsigned char *planar,
361  const unsigned int width, const unsigned int height)
362 {
363  volatile unsigned char *y, *u, *v;
364  unsigned int h, w;
365 
366  unsigned int wh = (width * height);
367  y = planar;
368  u = planar + (wh / 4);
369  v = u + (wh / 8);
370 
371  const unsigned int w_b_2 = width / 2;
372  const unsigned int w_b_4 = width / 4;
373  const unsigned int w_t_2 = width * 2;
374  unsigned int packpix;
375 
376  for (h = 0; h < height / 2; ++h) {
377  for (w = 0; w < width; w += 4) {
378  packpix = (h * w_t_2 + w) * 2;
379  y[h * w_b_2 + w / 2 ] = (packed[packpix + 0] + packed[packpix + 2]) / 2;
380  u[h * w_b_4 + w / 4 ] = (packed[packpix + 1] + packed[packpix + 5]) / 2;
381  y[h * w_b_2 + w / 2 + 1] = (packed[packpix + 4] + packed[packpix + 6]) / 2;
382  v[h * w_b_4 + w / 4 ] = (packed[packpix + 3] + packed[packpix + 7]) / 2;
383  }
384  }
385 }
386 
387 
388 void
389 yuv444packed_to_yuv422planar(const unsigned char *yuv444, unsigned char *yuv422,
390  unsigned int width, unsigned int height)
391 {
392  volatile unsigned char *y, *u, *v;
393  int i, iy, iiy;
394 
395  unsigned int wh = (width * height);
396  int wh2 = wh >> 1;
397  y = yuv422;
398  u = yuv422 + wh;
399  v = u + wh2;
400 
401 #ifdef ___OPENMP
402  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, yuv444) schedule(static)
403 #endif
404  for (i = 0; i < wh2; ++i) {
405  iy = i << 1;
406  iiy = i * 6;
407  y[iy] = yuv444[iiy];
408  y[iy+1] = yuv444[iiy + 3];
409  u[i] = (yuv444[iiy + 1] + yuv444[iiy + 4]) >> 1;
410  v[i] = (yuv444[iiy + 2] + yuv444[iiy + 5]) >> 1;
411  }
412 }
413 
414 
415 void
416 yuv444packed_to_yuv422packed(const unsigned char *yvu444, unsigned char *yuv422,
417  unsigned int width, unsigned int height)
418 {
419  int i, iiy;
420 
421  unsigned int wh = (width * height);
422  int wh2 = wh >> 1;
423 
424 #ifdef ___OPENMP
425 # pragma omp parallel for firstprivate(wh2) private(i, iiy) shared(yuv422, yvu444) schedule(static)
426 #endif
427  for (i = 0; i < wh2; i += 4) {
428  iiy = i * 6;
429  yuv422[i] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
430  yuv422[i+1] = yvu444[iiy];
431  yuv422[i+2] = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
432  yuv422[i+3] = yvu444[iiy + 3];
433  }
434 }
435 
436 
437 void
438 yvu444packed_to_yuv422planar(const unsigned char *yvu444, unsigned char *yuv422,
439  unsigned int width, unsigned int height)
440 {
441  volatile unsigned char *y, *u, *v;
442  int i, iy, iiy;
443 
444  unsigned int wh = (width * height);
445  int wh2 = wh >> 1;
446  y = yuv422;
447  u = yuv422 + wh;
448  v = u + wh2;
449 
450 #ifdef ___OPENMP
451 # pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, yvu444) schedule(static)
452 #endif
453  for (i = 0; i < wh2; ++i) {
454  iy = i << 1;
455  iiy = i * 6;
456  y[iy] = yvu444[iiy];
457  y[iy+1] = yvu444[iiy + 3];
458  u[i] = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
459  v[i] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
460  }
461 }
462 
463 
464 void
465 yvu444packed_to_yuv422packed(const unsigned char *yvu444, unsigned char *yuv422,
466  unsigned int width, unsigned int height)
467 {
468  int i, iiy;
469 
470  unsigned int wh = (width * height);
471  int wh2 = wh >> 1;
472 
473 #ifdef ___OPENMP
474 # pragma omp parallel for firstprivate(wh2) private(i, iiy) shared(yuv422, yvu444) schedule(static)
475 #endif
476  for (i = 0; i < wh2; i += 4) {
477  iiy = i * 6;
478  yuv422[i] = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
479  yuv422[i+1] = yvu444[iiy];
480  yuv422[i+2] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
481  yuv422[i+3] = yvu444[iiy + 3];
482  }
483 }
484 
485 
486 void
487 yuv422planar_erase_y_plane(unsigned char *yuv, unsigned int width, unsigned int height)
488 {
489  memset(yuv, 128, (width * height));
490 }
491 
492 
493 void
494 yuv422planar_erase_u_plane(unsigned char *yuv, unsigned int width, unsigned int height)
495 {
496  memset(yuv + (width * height), 128, (width * height / 2));
497 }
498 
499 
500 void
501 yuv422planar_erase_v_plane(unsigned char *yuv, unsigned int width, unsigned int height)
502 {
503  memset(yuv + (width * height * 3/2), 128, (width * height / 2));
504 }
505 
506 
507 void
508 grayscale_yuv422packed(const unsigned char *src, unsigned char *dst,
509  unsigned int width, unsigned int height)
510 {
511  unsigned int p = 0;
512  unsigned int d = 0;
513  while (p < colorspace_buffer_size(YUV422_PACKED, width, height)) {
514  if ( (p % 2) == 0 ) {
515  //dst[p] = 128;
516  } else {
517  dst[d++] = src[p];
518  }
519  p += 1;
520  }
521 }
522 
523 
524 void
525 grayscale_yuv422planar(const unsigned char *src, unsigned char *dst,
526  unsigned int width, unsigned int height)
527 {
528  memcpy(dst, src, width * height);
529  memset(dst + width * height, 128, width * height);
530 }
531 
532 } // end namespace firevision