Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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  register 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  register 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 
89 
90 /** Copy part of the U anv V planes of a YUV422planar image to another
91  */
92 void
93 yuv422planar_copy_uv(const unsigned char *src, unsigned char *dst,
94  unsigned int width, unsigned int height,
95  unsigned int x, unsigned int y,
96  unsigned int copy_width, unsigned int copy_height)
97 {
98 
99  register const unsigned char *sup = YUV422_PLANAR_U_PLANE(src, width, height) + (x / 2);
100  register const unsigned char *svp = YUV422_PLANAR_V_PLANE(src, width, height) + (x / 2);
101 
102  register unsigned char *dup = YUV422_PLANAR_U_PLANE(dst, width, height) + (x / 2);
103  register unsigned char *dvp = YUV422_PLANAR_V_PLANE(dst, width, height) + (x / 2);
104 
105  register unsigned int w;
106  register unsigned int h;
107 
108  unsigned const char *lsup = sup, *lsvp = svp, *ldup = dup, *ldvp = dvp;
109 
110  for (h = 0; h < copy_height; ++h) {
111  for ( w = 0; w < copy_width; w += 2 ) {
112  *dup++ = *sup++;
113  *dvp++ = *svp++;
114  }
115  lsup += width / 2;
116  lsvp += width / 2;
117  ldup += width / 2;
118  ldvp += width / 2;
119  }
120 }
121 
122 
123 void
124 yuv422planar_to_yuv422packed(const unsigned char *planar, unsigned char *packed,
125  unsigned int width, unsigned int height)
126 {
127  register const unsigned char *y, *u, *v;
128  register unsigned int i;
129 
130  y = planar;
131  u = planar + (width * height);
132  v = u + (width * height / 2);
133 
134  for (i = 0; i < (width * height / 2); ++i) {
135  *packed++ = *u++;
136  *packed++ = *y++;
137  *packed++ = *v++;
138  *packed++ = *y++;
139  }
140 }
141 
142 void
143 yuv422planar_quarter_to_yuv422packed(const unsigned char *planar, unsigned char *packed,
144  const unsigned int width,
145  const unsigned int height)
146 {
147  volatile const unsigned char *y, *u, *v;
148  register unsigned int w, h;
149 
150  const unsigned int w_h_4 = (width * height) / 4;
151  const unsigned int w_h_8 = (width * height) / 8;
152  const unsigned int w_t_2 = width * 2;
153  const unsigned int w_b_2 = width / 2;
154  const unsigned int w_b_4 = width / 4;
155 
156 
157  for (h = 0; h < height / 2; ++h) {
158  y = planar + (h * w_b_2);
159  u = planar + w_h_4 + (h * w_b_4);
160  v = planar + w_h_4 + w_h_8 + (h * w_b_4);
161 
162  for (w = 0; w < w_b_4; ++w) {
163  packed[h * w_t_2 + w * 4 ] = *u++;
164  packed[h * w_t_2 + w * 4 + 1] = *y++;
165  packed[h * w_t_2 + w * 4 + 2] = *v++;
166  packed[h * w_t_2 + w * 4 + 3] = *y++;
167  }
168  }
169 }
170 
171 
172 /* Convert quarter YUV422 planar buffer to plain YUV422 planar.
173  * @param quarter input buffer in YUV422_PLANAR_QUARTER
174  * @param output buffer in YUV422_PLANAR
175  * @param width width of the image (width of YUV422_PLANAR image)
176  * @param height height of the image (height of YUV422_PLANAR image)
177  */
178 void
179 yuv422planar_quarter_to_yuv422planar(const unsigned char *quarter,
180  unsigned char *planar,
181  const unsigned int width,
182  const unsigned int height)
183 {
184  volatile const unsigned char *y, *u, *v;
185  register unsigned int w, h;
186 
187  const unsigned int w_h_4 = (width * height) / 4;
188  const unsigned int w_h_8 = (width * height) / 8;
189  //const unsigned int w_t_2 = width * 2;
190  const unsigned int w_b_2 = width / 2;
191  const unsigned int w_b_4 = width / 4;
192 
193  unsigned char *yp, *up, *vp, t;
194  yp = planar;
195  up = YUV422_PLANAR_U_PLANE(planar, width, height);
196  vp = YUV422_PLANAR_V_PLANE(planar, width, height);
197 
198  for (h = 0; h < height / 2; ++h) {
199  y = quarter + (h * w_b_2);
200  u = quarter + w_h_4 + (h * w_b_4);
201  v = quarter + w_h_4 + w_h_8 + (h * w_b_4);
202 
203  for (w = 0; w < w_b_4; ++w) {
204  t = *y++;
205  *yp++ = t;
206  *yp++ = t;
207  t = *y++;
208  *yp++ = t;
209  *yp++ = t;
210  t = *u++;
211  *up++ = t;
212  *up++ = t;
213  t = *v++;
214  *vp++ = t;
215  *vp++ = t;
216  }
217 
218  memcpy(yp, yp - width, width);
219  memcpy(up, up - w_b_2, w_b_2);
220  memcpy(vp, vp - w_b_2, w_b_2);
221  yp += width;
222  up += w_b_2;
223  vp += w_b_2;
224  }
225 
226 }
227 
228 void
229 yuv422packed_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
230  unsigned int width, unsigned int height)
231 {
232  register volatile unsigned char *y, *u, *v;
233  register int i, iy, iiy;
234 
235  unsigned int wh = (width * height);
236  int wh2 = wh >> 1;
237  y = planar;
238  u = planar + wh;
239  v = u + wh2;
240 
241 #ifdef _OPENMP
242  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
243 #endif
244  for (i = 0; i < wh2; ++i) {
245  iy = i << 1;
246  iiy = iy << 1;
247  u[i] = packed[iiy];
248  y[iy] = packed[iiy + 1];
249  v[i] = packed[iiy + 2];
250  y[iy+1] = packed[iiy + 3];
251  }
252 }
253 
254 
255 void
256 yuy2_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
257  unsigned int width, unsigned int height)
258 {
259  register volatile unsigned char *y, *u, *v;
260  register int i, iy, iiy;
261 
262  unsigned int wh = (width * height);
263  int wh2 = wh >> 1;
264  y = planar;
265  u = planar + wh;
266  v = u + wh2;
267 
268 #ifdef _OPENMP
269  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
270 #endif
271  for (i = 0; i < wh2; ++i) {
272  iy = i << 1;
273  iiy = iy << 1;
274  y[iy] = packed[iiy];
275  u[i] = packed[iiy + 1];
276  y[iy+1] = packed[iiy + 2];
277  v[i] = packed[iiy + 3];
278  }
279 }
280 
281 
282 void
283 yvy2_to_yuv422planar(const unsigned char *packed, unsigned char *planar,
284  unsigned int width, unsigned int height)
285 {
286  register volatile unsigned char *y, *u, *v;
287  register int i, iy, iiy;
288 
289  unsigned int wh = (width * height);
290  int wh2 = wh >> 1;
291  y = planar;
292  u = planar + wh;
293  v = u + wh2;
294 
295 #ifdef _OPENMP
296  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, packed) schedule(static)
297 #endif
298  for (i = 0; i < wh2; ++i) {
299  iy = i << 1;
300  iiy = iy << 1;
301  y[iy] = packed[iiy];
302  v[i] = packed[iiy + 1];
303  y[iy+1] = packed[iiy + 2];
304  u[i] = packed[iiy + 3];
305  }
306 }
307 
308 
309 void
310 yuy2_to_yuv422planar_quarter(const unsigned char *packed, unsigned char *planar,
311  const unsigned int width, const unsigned int height)
312 {
313  register volatile unsigned char *y, *u, *v;
314  register unsigned int h, w;
315 
316  unsigned int wh = (width * height);
317  y = planar;
318  u = planar + (wh / 4);
319  v = u + (wh / 8);
320 
321  const unsigned int w_b_2 = width / 2;
322  const unsigned int w_b_4 = width / 4;
323  const unsigned int w_t_2 = width * 2;
324  unsigned int packpix;
325 
326  for (h = 0; h < height / 2; ++h) {
327  for (w = 0; w < width; w += 4) {
328  packpix = (h * w_t_2 + w) * 2;
329  y[h * w_b_2 + w / 2 ] = (packed[packpix + 0] + packed[packpix + 2]) / 2;
330  u[h * w_b_4 + w / 4 ] = (packed[packpix + 1] + packed[packpix + 5]) / 2;
331  y[h * w_b_2 + w / 2 + 1] = (packed[packpix + 4] + packed[packpix + 6]) / 2;
332  v[h * w_b_4 + w / 4 ] = (packed[packpix + 3] + packed[packpix + 7]) / 2;
333  }
334  }
335 }
336 
337 
338 void
339 yuv444packed_to_yuv422planar(const unsigned char *yuv444, unsigned char *yuv422,
340  unsigned int width, unsigned int height)
341 {
342  register volatile unsigned char *y, *u, *v;
343  register int i, iy, iiy;
344 
345  unsigned int wh = (width * height);
346  int wh2 = wh >> 1;
347  y = yuv422;
348  u = yuv422 + wh;
349  v = u + wh2;
350 
351 #ifdef ___OPENMP
352  #pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, yuv444) schedule(static)
353 #endif
354  for (i = 0; i < wh2; ++i) {
355  iy = i << 1;
356  iiy = i * 6;
357  y[iy] = yuv444[iiy];
358  y[iy+1] = yuv444[iiy + 3];
359  u[i] = (yuv444[iiy + 1] + yuv444[iiy + 4]) >> 1;
360  v[i] = (yuv444[iiy + 2] + yuv444[iiy + 5]) >> 1;
361  }
362 }
363 
364 
365 void
366 yuv444packed_to_yuv422packed(const unsigned char *yvu444, unsigned char *yuv422,
367  unsigned int width, unsigned int height)
368 {
369  register int i, iiy;
370 
371  unsigned int wh = (width * height);
372  int wh2 = wh >> 1;
373 
374 #ifdef ___OPENMP
375 # pragma omp parallel for firstprivate(wh2) private(i, iiy) shared(yuv422, yvu444) schedule(static)
376 #endif
377  for (i = 0; i < wh2; i += 4) {
378  iiy = i * 6;
379  yuv422[i] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
380  yuv422[i+1] = yvu444[iiy];
381  yuv422[i+2] = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
382  yuv422[i+3] = yvu444[iiy + 3];
383  }
384 }
385 
386 
387 void
388 yvu444packed_to_yuv422planar(const unsigned char *yvu444, unsigned char *yuv422,
389  unsigned int width, unsigned int height)
390 {
391  register volatile unsigned char *y, *u, *v;
392  register int i, iy, iiy;
393 
394  unsigned int wh = (width * height);
395  int wh2 = wh >> 1;
396  y = yuv422;
397  u = yuv422 + wh;
398  v = u + wh2;
399 
400 #ifdef ___OPENMP
401 # pragma omp parallel for firstprivate(wh2) private(i, iy, iiy) shared(y, u, v, yvu444) schedule(static)
402 #endif
403  for (i = 0; i < wh2; ++i) {
404  iy = i << 1;
405  iiy = i * 6;
406  y[iy] = yvu444[iiy];
407  y[iy+1] = yvu444[iiy + 3];
408  u[i] = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
409  v[i] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
410  }
411 }
412 
413 
414 void
415 yvu444packed_to_yuv422packed(const unsigned char *yvu444, unsigned char *yuv422,
416  unsigned int width, unsigned int height)
417 {
418  register int i, iiy;
419 
420  unsigned int wh = (width * height);
421  int wh2 = wh >> 1;
422 
423 #ifdef ___OPENMP
424 # pragma omp parallel for firstprivate(wh2) private(i, iiy) shared(yuv422, yvu444) schedule(static)
425 #endif
426  for (i = 0; i < wh2; i += 4) {
427  iiy = i * 6;
428  yuv422[i] = (yvu444[iiy + 2] + yvu444[iiy + 5]) >> 1;
429  yuv422[i+1] = yvu444[iiy];
430  yuv422[i+2] = (yvu444[iiy + 1] + yvu444[iiy + 4]) >> 1;
431  yuv422[i+3] = yvu444[iiy + 3];
432  }
433 }
434 
435 
436 void
437 yuv422planar_erase_y_plane(unsigned char *yuv, unsigned int width, unsigned int height)
438 {
439  memset(yuv, 128, (width * height));
440 }
441 
442 
443 void
444 yuv422planar_erase_u_plane(unsigned char *yuv, unsigned int width, unsigned int height)
445 {
446  memset(yuv + (width * height), 128, (width * height / 2));
447 }
448 
449 
450 void
451 yuv422planar_erase_v_plane(unsigned char *yuv, unsigned int width, unsigned int height)
452 {
453  memset(yuv + (width * height * 3/2), 128, (width * height / 2));
454 }
455 
456 
457 void
458 grayscale_yuv422packed(const unsigned char *src, unsigned char *dst,
459  unsigned int width, unsigned int height)
460 {
461  unsigned int p = 0;
462  unsigned int d = 0;
463  while (p < colorspace_buffer_size(YUV422_PACKED, width, height)) {
464  if ( (p % 2) == 0 ) {
465  //dst[p] = 128;
466  } else {
467  dst[d++] = src[p];
468  }
469  p += 1;
470  }
471 }
472 
473 
474 void
475 grayscale_yuv422planar(const unsigned char *src, unsigned char *dst,
476  unsigned int width, unsigned int height)
477 {
478  memcpy(dst, src, width * height);
479  memset(dst + width * height, 128, width * height);
480 }
481 
482 } // end namespace firevision