Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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  register int y0, y1, u0, u1, v0, v1 ;
42  register 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  register unsigned int i = 0, j = 0;
82  register int y[4] = {0, 0, 0, 0}, u, v;
83  register RGB_t *r;
84  register unsigned int su = 0;
85  register unsigned int sv = 0;
86 
87  while (i < (width * height)) {
88  r = (RGB_t *)RGB;
89  for (register 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  register unsigned int i = 0;
122  register int y1, y2, u1, u2, v1, v2;
123  register RGB_t *r1, *r2;
124  register 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  register unsigned int i = 0;
165  register int y1, y2, u1, u2, v1, v2;
166  register RGB_t *r1, *r2;
167  register 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  register unsigned int i = 0;
208  register int y1, y2, u1, u2, v1, v2;
209  register RGB_t *r1, *r2;
210  register 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 /* Convert an RGB buffer to a packed YUV422 buffer, see above for general notes about color space
235  * conversion from RGB to YUV
236  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
237  * (thus this is a 24bit RGB with one byte per color) line by line.
238  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
239  * line
240  * @param width Width of the image contained in the RGB buffer
241  * @param height Height of the image contained in the RGB buffer
242  */
243 void
244 rgb_to_yuv422packed_plainc(const unsigned char *RGB, unsigned char *YUV,
245  unsigned int width, unsigned int height)
246 {
247  register unsigned int i = 0;
248  register int y1, y2, u1, u2, v1, v2;
249  register RGB_t *r1, *r2;
250  register unsigned char *p;
251 
252  p = YUV;
253 
254  while (i < (width * height)) {
255  r1 = (RGB_t *)RGB;
256  RGB += 3;
257  r2 = (RGB_t *)RGB;
258  RGB += 3;
259 
260  RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
261  RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
262 
263  *p++ = (u1 + u2) / 2;
264  *p++ = y1;
265  *p++ = (v1 + v2) / 2;
266  *p++ = y2;
267 
268  i += 2;
269  }
270 }
271 
272 /** Convert an BGR buffer to a planar YUV422 buffer.
273  * See above for general notes about color space conversion from RGB to YUV.
274  * @param RGB unsigned char array that contains the pixels, pixel after pixel, 3 bytes per pixel
275  * (thus this is a 24bit RGB with one byte per color) line by line.
276  * @param YUV where the YUV output will be written to, will have 4 pixels in 6 byte macro pixel, line after
277  * line
278  * @param width Width of the image contained in the RGB buffer
279  * @param height Height of the image contained in the RGB buffer
280  */
281 void
282 bgr_to_yuv422planar_plainc(const unsigned char *BGR, unsigned char *YUV,
283  unsigned int width, unsigned int height)
284 {
285  register unsigned int i = 0;
286  register int y1, y2, u1, u2, v1, v2;
287  register BGR_t *r1, *r2;
288  register unsigned char *yp, *up, *vp;
289 
290  yp = YUV;
291  up = YUV422_PLANAR_U_PLANE(YUV, width, height);
292  vp = YUV422_PLANAR_V_PLANE(YUV, width, height);
293 
294  while (i < (width * height)) {
295  r1 = (BGR_t *)BGR;
296  BGR += 3;
297  r2 = (BGR_t *)BGR;
298  BGR += 3;
299 
300  RGB2YUV(r1->R, r1->G, r1->B, y1, u1, v1);
301  RGB2YUV(r2->R, r2->G, r2->B, y2, u2, v2);
302 
303  *yp++ = y1;
304  *yp++ = y2;
305  *up++ = (u1 + u2) / 2;
306  *vp++ = (v1 + v2) / 2;
307 
308  i += 2;
309  }
310 }
311 
312 } // end namespace firevision