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