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
32namespace firevision {
33
34void
35rgb_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 */
73void
74rgb_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 */
113void
114convert_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 */
159void
160rgb_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 */
203void
204convert_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 */
247void
248rgb_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
278void
279rgb_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 */
323void
324bgr_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