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