Fawkes API  Fawkes Development Version
rgbyuv.cpp
1 
2 /****************************************************************************
3  * rgbyuv.h - RGB to YUV conversion - specific methods, macros and constants
4  *
5  * Created: Sat Aug 12 15:21:39 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/rgb.h>
27 #include <fvutils/color/rgbyuv.h>
28 #include <fvutils/color/yuv.h>
29 
30 #include <cstring>
31 
32 namespace firevision {
33 
34 void
35 rgb_to_yuy2(const unsigned char *RGB, unsigned char *YUV, unsigned int width, unsigned int height)
36 {
37  unsigned int i, j;
38  int y0, y1, u0, u1, v0, v1;
39  int r, g, b;
40 
41  for (i = 0, j = 0; i < 3 * width * height; i += 6, j += 4) {
42  r = RGB[i + 0];
43  g = RGB[i + 1];
44  b = RGB[i + 2];
45  RGB2YUV(r, g, b, y0, u0, v0);
46  r = RGB[i + 3];
47  g = RGB[i + 4];
48  b = RGB[i + 5];
49  RGB2YUV(r, g, b, y1, u1, v1);
50  YUV[j + 0] = y0;
51  YUV[j + 1] = (u0 + u1) / 2;
52  YUV[j + 2] = y1;
53  YUV[j + 3] = (v0 + v1) / 2;
54  }
55 }
56 
57 /** RGB to YUV Conversion
58  *
59  * Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
60  * Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
61  * Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
62  *
63  * Values have to be clamped to keep them in the [0-255] range.
64  * Rumour has it that the valid range is actually a subset of [0-255] (fourcc.org mentions an RGB range
65  * of [16-235]) but clamping the values into [0-255] seems to produce acceptable results.
66  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
67  * (thus this is a 24bit RGB with one byte per color) line by line.
68  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
69  * line
70  * @param width Width of the image contained in the RGB buffer
71  * @param height Height of the image contained in the RGB buffer
72  */
73 void
74 rgb_to_yuv411packed_plainc(const unsigned char *RGB,
75  unsigned char * YUV,
76  unsigned int width,
77  unsigned int height)
78 {
79  unsigned int i = 0, j = 0;
80  int y[4] = {0, 0, 0, 0}, u, v;
81  RGB_t * r;
82  unsigned int su = 0;
83  unsigned int sv = 0;
84 
85  while (i < (width * height)) {
86  r = (RGB_t *)RGB;
87  for (unsigned int k = 0; j <= 4; ++j) {
88  RGB2YUV(r->R, r->G, r->B, y[k], u, v);
89  su += u;
90  sv += v;
91  RGB += 3;
92  }
93  YUV[j++] = su / 4;
94  YUV[j++] = y[0];
95  YUV[j++] = y[1];
96  YUV[j++] = sv / 4;
97  YUV[j++] = y[2];
98  YUV[j++] = y[3];
99  }
100 }
101 
102 /** Convert a line of a RGB buffer to a line in a planar YUV422 buffer.
103  * See above for general notes about color space conversion from RGB to YUV.
104  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
105  * (thus this is a 24bit RGB with one byte per color) line by line.
106  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
107  * line
108  * @param width Width of the image contained in the RGB buffer
109  * @param height Height of the image contained in the RGB buffer
110  * @param rgb_line the index of the line to be converted
111  * @param yuv_line the index of the line to convert to in the YUV buffer
112  */
113 void
114 convert_line_rgb_to_yuv422planar(const unsigned char *RGB,
115  unsigned char * YUV,
116  unsigned int width,
117  unsigned int height,
118  unsigned int rgb_line,
119  unsigned int yuv_line)
120 {
121  unsigned int i = 0;
122  int y1, y2, u1, u2, v1, v2;
123  RGB_t * r1, *r2;
124  unsigned char *yp, *up, *vp;
125 
126  yp = YUV + (width * yuv_line);
127  up = YUV422_PLANAR_U_PLANE(YUV, width, height) + (width * yuv_line / 2);
128  vp = YUV422_PLANAR_V_PLANE(YUV, width, height) + (width * yuv_line / 2);
129 
130  RGB += 3 * width * rgb_line;
131 
132  while (i < width) {
133  r1 = (RGB_t *)RGB;
134  RGB += 3;
135  r2 = (RGB_t *)RGB;
136  RGB += 3;
137 
138  RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
139  RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
140 
141  *yp++ = y1;
142  *yp++ = y2;
143  *up++ = (u1 + u2) / 2;
144  *vp++ = (v1 + v2) / 2;
145 
146  i += 2;
147  }
148 }
149 
150 /** Convert an RGB buffer to a planar YUV422 buffer.
151  * See above for general notes about color space conversion from RGB to YUV.
152  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
153  * (thus this is a 24bit RGB with one byte per color) line by line.
154  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
155  * line
156  * @param width Width of the image contained in the RGB buffer
157  * @param height Height of the image contained in the RGB buffer
158  */
159 void
160 rgb_to_yuv422planar_plainc(const unsigned char *RGB,
161  unsigned char * YUV,
162  unsigned int width,
163  unsigned int height)
164 {
165  unsigned int i = 0;
166  int y1, y2, u1, u2, v1, v2;
167  RGB_t * r1, *r2;
168  unsigned char *yp, *up, *vp;
169 
170  yp = YUV;
171  up = YUV422_PLANAR_U_PLANE(YUV, width, height);
172  vp = YUV422_PLANAR_V_PLANE(YUV, width, height);
173 
174  while (i < (width * height)) {
175  r1 = (RGB_t *)RGB;
176  RGB += 3;
177  r2 = (RGB_t *)RGB;
178  RGB += 3;
179 
180  RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
181  RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
182 
183  *yp++ = y1;
184  *yp++ = y2;
185  *up++ = (u1 + u2) / 2;
186  *vp++ = (v1 + v2) / 2;
187 
188  i += 2;
189  }
190 }
191 
192 /* Convert a line of a RGB buffer to a line in a packed YUV422 buffer, see above for general
193  * notes about color space conversion from RGB to YUV
194  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
195  * (thus this is a 24bit RGB with one byte per color) line by line.
196  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
197  * line
198  * @param width Width of the image contained in the RGB buffer
199  * @param height Height of the image contained in the RGB buffer
200  * @param rgb_line the index of the line to be converted
201  * @param yuv_line the index of the line to convert to in the YUV buffer
202  */
203 void
204 convert_line_rgb_to_yuv422packed(const unsigned char *RGB,
205  unsigned char * YUV,
206  unsigned int width,
207  unsigned int height,
208  unsigned int rgb_line,
209  unsigned int yuv_line)
210 {
211  unsigned int i = 0;
212  int y1, y2, u1, u2, v1, v2;
213  RGB_t * r1, *r2;
214  unsigned char *p;
215 
216  p = YUV + (width * yuv_line) * 2;
217 
218  RGB += 3 * width * rgb_line;
219 
220  while (i < width) {
221  r1 = (RGB_t *)RGB;
222  RGB += 3;
223  r2 = (RGB_t *)RGB;
224  RGB += 3;
225 
226  RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
227  RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
228 
229  *p++ = (u1 + u2) / 2;
230  *p++ = y1;
231  *p++ = (v1 + v2) / 2;
232  *p++ = y2;
233 
234  i += 2;
235  }
236 }
237 
238 /* Convert an RGB buffer to a packed YUV422 buffer, see above for general notes about color space
239  * conversion from RGB to YUV
240  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
241  * (thus this is a 24bit RGB with one byte per color) line by line.
242  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
243  * line
244  * @param width Width of the image contained in the RGB buffer
245  * @param height Height of the image contained in the RGB buffer
246  */
247 void
248 rgb_to_yuv422packed_plainc(const unsigned char *RGB,
249  unsigned char * YUV,
250  unsigned int width,
251  unsigned int height)
252 {
253  unsigned int i = 0;
254  int y1, y2, u1, u2, v1, v2;
255  RGB_t * r1, *r2;
256  unsigned char *p;
257 
258  p = YUV;
259 
260  while (i < (width * height)) {
261  r1 = (RGB_t *)RGB;
262  RGB += 3;
263  r2 = (RGB_t *)RGB;
264  RGB += 3;
265 
266  RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
267  RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
268 
269  *p++ = (u1 + u2) / 2;
270  *p++ = y1;
271  *p++ = (v1 + v2) / 2;
272  *p++ = y2;
273 
274  i += 2;
275  }
276 }
277 
278 void
279 rgb_planar_to_yuv422packed_plainc(const unsigned char *rgb_planar,
280  unsigned char * YUV,
281  unsigned int width,
282  unsigned int height)
283 {
284  const unsigned char *r = rgb_planar;
285  const unsigned char *g = rgb_planar + (width * height);
286  const unsigned char *b = rgb_planar + (width * height * 2);
287 
288  unsigned int i = 0;
289  int y1, y2, u1, u2, v1, v2;
290  unsigned char *p;
291  unsigned char r1, r2, g1, g2, b1, b2;
292 
293  p = YUV;
294 
295  while (i < (width * height)) {
296  r1 = *r++;
297  r2 = *r++;
298  g1 = *g++;
299  g2 = *g++;
300  b1 = *b++;
301  b2 = *b++;
302  RGB2YUV(r1, g1, b1, y1, u1, v1);
303  RGB2YUV(r2, g2, b2, y2, u2, v2);
304 
305  *p++ = (u1 + u2) / 2;
306  *p++ = y1;
307  *p++ = (v1 + v2) / 2;
308  *p++ = y2;
309 
310  i += 2;
311  }
312 }
313 
314 /** Convert an BGR buffer to a planar YUV422 buffer.
315  * See above for general notes about color space conversion from RGB to YUV.
316  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
317  * (thus this is a 24bit RGB with one byte per color) line by line.
318  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
319  * line
320  * @param width Width of the image contained in the RGB buffer
321  * @param height Height of the image contained in the RGB buffer
322  */
323 void
324 bgr_to_yuv422planar_plainc(const unsigned char *BGR,
325  unsigned char * YUV,
326  unsigned int width,
327  unsigned int height)
328 {
329  unsigned int i = 0;
330  int y1, y2, u1, u2, v1, v2;
331  BGR_t * r1, *r2;
332  unsigned char *yp, *up, *vp;
333 
334  yp = YUV;
335  up = YUV422_PLANAR_U_PLANE(YUV, width, height);
336  vp = YUV422_PLANAR_V_PLANE(YUV, width, height);
337 
338  while (i < (width * height)) {
339  r1 = (BGR_t *)BGR;
340  BGR += 3;
341  r2 = (BGR_t *)BGR;
342  BGR += 3;
343 
344  RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
345  RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
346 
347  *yp++ = y1;
348  *yp++ = y2;
349  *up++ = (u1 + u2) / 2;
350  *vp++ = (v1 + v2) / 2;
351 
352  i += 2;
353  }
354 }
355 
356 } // end namespace firevision