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
30namespace firevision {
31
32void
33iyu1_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 */
60void
61gray8_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 */
77void
78gray8_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 */
91void
92gray8_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 */
108void
109yuv422planar_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 */
143void
144yuv420planar_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
177void
178yuv422planar_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
198void
199yuv422planar_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 */
233void
234yuv422planar_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
282void
283yuv422packed_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
311void
312yuy2_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
340void
341yvy2_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
369void
370yuy2_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
399void
400yuv444packed_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
428void
429yuv444packed_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
451void
452yvu444packed_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
480void
481yvu444packed_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
503void
504yuv422planar_erase_y_plane(unsigned char *yuv, unsigned int width, unsigned int height)
505{
506 memset(yuv, 128, (width * height));
507}
508
509void
510yuv422planar_erase_u_plane(unsigned char *yuv, unsigned int width, unsigned int height)
511{
512 memset(yuv + (width * height), 128, (width * height / 2));
513}
514
515void
516yuv422planar_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
521void
522grayscale_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
539void
540grayscale_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