1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "cameraformatconverter.h" |
|
43 #include <QDebug> |
|
44 |
|
45 /* |
|
46 Create a format converter |
|
47 */ |
|
48 |
|
49 CameraFormatConverter* CameraFormatConverter::createFormatConverter(QVideoFrame::PixelFormat format, int width, int height) |
|
50 { |
|
51 if(format == QVideoFrame::Format_YUYV) |
|
52 return new YUVConverter(format,width,height); |
|
53 else if(format == QVideoFrame::Format_UYVY) |
|
54 return new YUVConverter(format,width,height); |
|
55 else if(format == QVideoFrame::Format_YUV420P) |
|
56 return new YUVConverter(format,width,height); |
|
57 else |
|
58 return new NullConverter; |
|
59 } |
|
60 |
|
61 void CameraFormatConverter::releaseFormatConverter(CameraFormatConverter* converter) |
|
62 { |
|
63 delete converter; |
|
64 } |
|
65 |
|
66 |
|
67 // Null Converter |
|
68 unsigned char* NullConverter::convert(unsigned char* src, int len) |
|
69 { |
|
70 Q_UNUSED(len) |
|
71 return src; |
|
72 } |
|
73 |
|
74 QList<QVideoFrame::PixelFormat> CameraFormatConverter::supportedFormats() |
|
75 { |
|
76 QList<QVideoFrame::PixelFormat> list; |
|
77 list << QVideoFrame::Format_RGB24 << QVideoFrame::Format_YUYV << QVideoFrame::Format_RGB32 |
|
78 << QVideoFrame::Format_UYVY << QVideoFrame::Format_YUV420P << QVideoFrame::Format_RGB555; |
|
79 return list; |
|
80 } |
|
81 |
|
82 // YUV |
|
83 YUVConverter::YUVConverter(QVideoFrame::PixelFormat type,int width, int height): |
|
84 m_type(type), |
|
85 m_width(width), |
|
86 m_height(height) |
|
87 { |
|
88 m_buf = new unsigned char[width * height * 2]; |
|
89 |
|
90 if (m_type == QVideoFrame::Format_YUYV) { |
|
91 // For YUY2 format use these to match (Y0-U0-Y1-V0) |
|
92 m_y1i=0; |
|
93 m_ui =1; |
|
94 m_y2i=2; |
|
95 m_vi =3; |
|
96 } else if(m_type == QVideoFrame::Format_UYVY) { |
|
97 m_y1i=1; |
|
98 m_ui =0; |
|
99 m_y2i=3; |
|
100 m_vi =2; |
|
101 } |
|
102 } |
|
103 |
|
104 YUVConverter::~YUVConverter() |
|
105 { |
|
106 delete [] m_buf; |
|
107 } |
|
108 |
|
109 |
|
110 static const signed short redAdjust[] = { |
|
111 -161,-160,-159,-158,-157,-156,-155,-153, |
|
112 -152,-151,-150,-149,-148,-147,-145,-144, |
|
113 -143,-142,-141,-140,-139,-137,-136,-135, |
|
114 -134,-133,-132,-131,-129,-128,-127,-126, |
|
115 -125,-124,-123,-122,-120,-119,-118,-117, |
|
116 -116,-115,-114,-112,-111,-110,-109,-108, |
|
117 -107,-106,-104,-103,-102,-101,-100, -99, |
|
118 -98, -96, -95, -94, -93, -92, -91, -90, |
|
119 -88, -87, -86, -85, -84, -83, -82, -80, |
|
120 -79, -78, -77, -76, -75, -74, -72, -71, |
|
121 -70, -69, -68, -67, -66, -65, -63, -62, |
|
122 -61, -60, -59, -58, -57, -55, -54, -53, |
|
123 -52, -51, -50, -49, -47, -46, -45, -44, |
|
124 -43, -42, -41, -39, -38, -37, -36, -35, |
|
125 -34, -33, -31, -30, -29, -28, -27, -26, |
|
126 -25, -23, -22, -21, -20, -19, -18, -17, |
|
127 -16, -14, -13, -12, -11, -10, -9, -8, |
|
128 -6, -5, -4, -3, -2, -1, 0, 1, |
|
129 2, 3, 4, 5, 6, 7, 9, 10, |
|
130 11, 12, 13, 14, 15, 17, 18, 19, |
|
131 20, 21, 22, 23, 25, 26, 27, 28, |
|
132 29, 30, 31, 33, 34, 35, 36, 37, |
|
133 38, 39, 40, 42, 43, 44, 45, 46, |
|
134 47, 48, 50, 51, 52, 53, 54, 55, |
|
135 56, 58, 59, 60, 61, 62, 63, 64, |
|
136 66, 67, 68, 69, 70, 71, 72, 74, |
|
137 75, 76, 77, 78, 79, 80, 82, 83, |
|
138 84, 85, 86, 87, 88, 90, 91, 92, |
|
139 93, 94, 95, 96, 97, 99, 100, 101, |
|
140 102, 103, 104, 105, 107, 108, 109, 110, |
|
141 111, 112, 113, 115, 116, 117, 118, 119, |
|
142 120, 121, 123, 124, 125, 126, 127, 128, |
|
143 }; |
|
144 |
|
145 static const signed short greenAdjust1[] = { |
|
146 34, 34, 33, 33, 32, 32, 32, 31, |
|
147 31, 30, 30, 30, 29, 29, 28, 28, |
|
148 28, 27, 27, 27, 26, 26, 25, 25, |
|
149 25, 24, 24, 23, 23, 23, 22, 22, |
|
150 21, 21, 21, 20, 20, 19, 19, 19, |
|
151 18, 18, 17, 17, 17, 16, 16, 15, |
|
152 15, 15, 14, 14, 13, 13, 13, 12, |
|
153 12, 12, 11, 11, 10, 10, 10, 9, |
|
154 9, 8, 8, 8, 7, 7, 6, 6, |
|
155 6, 5, 5, 4, 4, 4, 3, 3, |
|
156 2, 2, 2, 1, 1, 0, 0, 0, |
|
157 0, 0, -1, -1, -1, -2, -2, -2, |
|
158 -3, -3, -4, -4, -4, -5, -5, -6, |
|
159 -6, -6, -7, -7, -8, -8, -8, -9, |
|
160 -9, -10, -10, -10, -11, -11, -12, -12, |
|
161 -12, -13, -13, -14, -14, -14, -15, -15, |
|
162 -16, -16, -16, -17, -17, -17, -18, -18, |
|
163 -19, -19, -19, -20, -20, -21, -21, -21, |
|
164 -22, -22, -23, -23, -23, -24, -24, -25, |
|
165 -25, -25, -26, -26, -27, -27, -27, -28, |
|
166 -28, -29, -29, -29, -30, -30, -30, -31, |
|
167 -31, -32, -32, -32, -33, -33, -34, -34, |
|
168 -34, -35, -35, -36, -36, -36, -37, -37, |
|
169 -38, -38, -38, -39, -39, -40, -40, -40, |
|
170 -41, -41, -42, -42, -42, -43, -43, -44, |
|
171 -44, -44, -45, -45, -45, -46, -46, -47, |
|
172 -47, -47, -48, -48, -49, -49, -49, -50, |
|
173 -50, -51, -51, -51, -52, -52, -53, -53, |
|
174 -53, -54, -54, -55, -55, -55, -56, -56, |
|
175 -57, -57, -57, -58, -58, -59, -59, -59, |
|
176 -60, -60, -60, -61, -61, -62, -62, -62, |
|
177 -63, -63, -64, -64, -64, -65, -65, -66, |
|
178 }; |
|
179 |
|
180 static const signed short greenAdjust2[] = { |
|
181 74, 73, 73, 72, 71, 71, 70, 70, |
|
182 69, 69, 68, 67, 67, 66, 66, 65, |
|
183 65, 64, 63, 63, 62, 62, 61, 60, |
|
184 60, 59, 59, 58, 58, 57, 56, 56, |
|
185 55, 55, 54, 53, 53, 52, 52, 51, |
|
186 51, 50, 49, 49, 48, 48, 47, 47, |
|
187 46, 45, 45, 44, 44, 43, 42, 42, |
|
188 41, 41, 40, 40, 39, 38, 38, 37, |
|
189 37, 36, 35, 35, 34, 34, 33, 33, |
|
190 32, 31, 31, 30, 30, 29, 29, 28, |
|
191 27, 27, 26, 26, 25, 24, 24, 23, |
|
192 23, 22, 22, 21, 20, 20, 19, 19, |
|
193 18, 17, 17, 16, 16, 15, 15, 14, |
|
194 13, 13, 12, 12, 11, 11, 10, 9, |
|
195 9, 8, 8, 7, 6, 6, 5, 5, |
|
196 4, 4, 3, 2, 2, 1, 1, 0, |
|
197 0, 0, -1, -1, -2, -2, -3, -4, |
|
198 -4, -5, -5, -6, -6, -7, -8, -8, |
|
199 -9, -9, -10, -11, -11, -12, -12, -13, |
|
200 -13, -14, -15, -15, -16, -16, -17, -17, |
|
201 -18, -19, -19, -20, -20, -21, -22, -22, |
|
202 -23, -23, -24, -24, -25, -26, -26, -27, |
|
203 -27, -28, -29, -29, -30, -30, -31, -31, |
|
204 -32, -33, -33, -34, -34, -35, -35, -36, |
|
205 -37, -37, -38, -38, -39, -40, -40, -41, |
|
206 -41, -42, -42, -43, -44, -44, -45, -45, |
|
207 -46, -47, -47, -48, -48, -49, -49, -50, |
|
208 -51, -51, -52, -52, -53, -53, -54, -55, |
|
209 -55, -56, -56, -57, -58, -58, -59, -59, |
|
210 -60, -60, -61, -62, -62, -63, -63, -64, |
|
211 -65, -65, -66, -66, -67, -67, -68, -69, |
|
212 -69, -70, -70, -71, -71, -72, -73, -73, |
|
213 }; |
|
214 |
|
215 static const signed short blueAdjust[] = { |
|
216 -276,-274,-272,-270,-267,-265,-263,-261, |
|
217 -259,-257,-255,-253,-251,-249,-247,-245, |
|
218 -243,-241,-239,-237,-235,-233,-231,-229, |
|
219 -227,-225,-223,-221,-219,-217,-215,-213, |
|
220 -211,-209,-207,-204,-202,-200,-198,-196, |
|
221 -194,-192,-190,-188,-186,-184,-182,-180, |
|
222 -178,-176,-174,-172,-170,-168,-166,-164, |
|
223 -162,-160,-158,-156,-154,-152,-150,-148, |
|
224 -146,-144,-141,-139,-137,-135,-133,-131, |
|
225 -129,-127,-125,-123,-121,-119,-117,-115, |
|
226 -113,-111,-109,-107,-105,-103,-101, -99, |
|
227 -97, -95, -93, -91, -89, -87, -85, -83, |
|
228 -81, -78, -76, -74, -72, -70, -68, -66, |
|
229 -64, -62, -60, -58, -56, -54, -52, -50, |
|
230 -48, -46, -44, -42, -40, -38, -36, -34, |
|
231 -32, -30, -28, -26, -24, -22, -20, -18, |
|
232 -16, -13, -11, -9, -7, -5, -3, -1, |
|
233 0, 2, 4, 6, 8, 10, 12, 14, |
|
234 16, 18, 20, 22, 24, 26, 28, 30, |
|
235 32, 34, 36, 38, 40, 42, 44, 46, |
|
236 49, 51, 53, 55, 57, 59, 61, 63, |
|
237 65, 67, 69, 71, 73, 75, 77, 79, |
|
238 81, 83, 85, 87, 89, 91, 93, 95, |
|
239 97, 99, 101, 103, 105, 107, 109, 112, |
|
240 114, 116, 118, 120, 122, 124, 126, 128, |
|
241 130, 132, 134, 136, 138, 140, 142, 144, |
|
242 146, 148, 150, 152, 154, 156, 158, 160, |
|
243 162, 164, 166, 168, 170, 172, 175, 177, |
|
244 179, 181, 183, 185, 187, 189, 191, 193, |
|
245 195, 197, 199, 201, 203, 205, 207, 209, |
|
246 211, 213, 215, 217, 219, 221, 223, 225, |
|
247 227, 229, 231, 233, 235, 238, 240, 242, |
|
248 }; |
|
249 |
|
250 |
|
251 |
|
252 #define CLAMP(x) x < 0 ? 0 : x & 0xff |
|
253 |
|
254 inline void yuv2rgb565(int y, int u, int v, quint16 *rgb) |
|
255 { |
|
256 register int r, g, b; |
|
257 |
|
258 r = y + redAdjust[v]; |
|
259 g = y + greenAdjust1[u] + greenAdjust2[v]; |
|
260 b = y + blueAdjust[u]; |
|
261 |
|
262 #if 0 |
|
263 y -= 16; |
|
264 u -= 128; |
|
265 v -= 128; |
|
266 r = y + 1.13983*v; |
|
267 g = y + 0.39465*u - 0.58060*v; |
|
268 b = y + 2.03211*u; |
|
269 #endif |
|
270 |
|
271 r = CLAMP(r); |
|
272 g = CLAMP(g); |
|
273 b = CLAMP(b); |
|
274 |
|
275 *rgb = (quint16)(((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); |
|
276 } |
|
277 |
|
278 inline void yuv2rgb24(int y, int u, int v, quint32 *rgb) |
|
279 { |
|
280 register int r, g, b; |
|
281 |
|
282 r = y + redAdjust[v]; |
|
283 g = y + greenAdjust1[u] + greenAdjust2[v]; |
|
284 b = y + blueAdjust[u]; |
|
285 |
|
286 r = CLAMP(r); |
|
287 g = CLAMP(g); |
|
288 b = CLAMP(b); |
|
289 |
|
290 *rgb = ((r<<24)|(g<<16) | b) | 0xff000000 ; |
|
291 } |
|
292 |
|
293 #define yuv2rgb(a,b,c,d) yuv2rgb565(a,b,c,d) |
|
294 |
|
295 unsigned char* YUVConverter::convert(unsigned char* src, int len) |
|
296 { |
|
297 quint16* dest = (quint16*)m_buf; |
|
298 unsigned char *buf = src; |
|
299 int size = (m_width * m_height) >> 1; |
|
300 |
|
301 |
|
302 #define CONV \ |
|
303 {\ |
|
304 register int u = buf[m_ui];\ |
|
305 register int v = buf[m_vi];\ |
|
306 yuv2rgb(buf[m_y1i], u, v, dest);\ |
|
307 yuv2rgb(buf[m_y2i], u, v, ++dest);\ |
|
308 dest++;\ |
|
309 buf+= 4;\ |
|
310 } |
|
311 if (m_type != QVideoFrame::Format_YUV420P) { |
|
312 register int n = (size + 7) / 8; |
|
313 switch(size & 7) |
|
314 { |
|
315 case 0: do {CONV |
|
316 case 7: CONV |
|
317 case 6: CONV |
|
318 case 5: CONV |
|
319 case 4: CONV |
|
320 case 3: CONV |
|
321 case 2: CONV |
|
322 case 1: CONV |
|
323 } while(--n); |
|
324 } |
|
325 } else { |
|
326 // for 320x240 use 353x288, only works for this res!! |
|
327 int w = m_width; |
|
328 int h = m_height; |
|
329 int Ysize = w * h; |
|
330 if(len == Ysize+Ysize/4+Ysize/4) { |
|
331 for(int y=0;y<m_height;y++) { |
|
332 for(int x=0;x<m_width;x++) { |
|
333 int yy = (int)buf[y*w+x]; |
|
334 int u = (int)buf[(y/2)*(w/2)+x/2+Ysize]; |
|
335 int v = (int)buf[(y/2)*(w/2)+x/2+Ysize+Ysize/4]; |
|
336 yuv2rgb565(yy,u,v,dest); |
|
337 dest++; |
|
338 } |
|
339 } |
|
340 } else { |
|
341 qWarning("buffer provided doesn't match expected size!!!"); |
|
342 } |
|
343 } |
|
344 |
|
345 return m_buf; |
|
346 |
|
347 } |
|
348 |
|
349 /* |
|
350 * convert ROUTINE TAKEN FROM: |
|
351 * |
|
352 * Sonix SN9C101 based webcam basic I/F routines |
|
353 * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp> |
|
354 * |
|
355 * Redistribution and use in source and binary forms, with or without |
|
356 * modification, are permitted provided that the following conditions |
|
357 * are met: |
|
358 * 1. Redistributions of source code must retain the above copyright |
|
359 * notice, this list of conditions and the following disclaimer. |
|
360 * 2. Redistributions in binary form must reproduce the above copyright |
|
361 * notice, this list of conditions and the following disclaimer in the |
|
362 * documentation and/or other materials provided with the distribution. |
|
363 * |
|
364 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
|
365 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
366 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
367 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
|
368 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
369 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
370 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
371 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
372 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
373 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
374 * SUCH DAMAGE. |
|
375 */ |
|
376 |
|
377 BayerConverter::BayerConverter(int width, int height): |
|
378 m_width(width), |
|
379 m_height(height) |
|
380 { |
|
381 m_buf = new unsigned char[width * height * 4]; // 4 = 32bpp / 8 bpb |
|
382 } |
|
383 |
|
384 BayerConverter::~BayerConverter() |
|
385 { |
|
386 delete m_buf; |
|
387 } |
|
388 |
|
389 unsigned char* BayerConverter::convert(unsigned char* src, int len) |
|
390 { |
|
391 Q_UNUSED(len) |
|
392 |
|
393 int size = m_width * m_height; |
|
394 unsigned long *dst = (unsigned long*) m_buf; |
|
395 |
|
396 register unsigned long dstVal; |
|
397 |
|
398 for (int i = 0; i < size; ++i) |
|
399 { |
|
400 dstVal = 0xFF000000; |
|
401 |
|
402 if ((i / m_width) % 2 == 0) |
|
403 { |
|
404 if (!(i & 1)) |
|
405 { |
|
406 /* B */ |
|
407 if ((i > m_width) && ((i % m_width) > 0) ) |
|
408 { |
|
409 dstVal |= ((*(src-m_width-1)+*(src-m_width+1)+ *(src+m_width-1)+*(src+m_width + 1)) / 4) << 16 | |
|
410 ((*(src-1)+*(src+1)+*(src+m_width)+*(src-m_width))/4) << 8 | |
|
411 *src; |
|
412 } |
|
413 else |
|
414 { |
|
415 dstVal |= *(src + m_width + 1) << 16 | |
|
416 (*(src + 1) + *(src + m_width)) / 2 << 8 | |
|
417 *src; |
|
418 } |
|
419 } |
|
420 else |
|
421 { |
|
422 /* (B)G */ |
|
423 if ((i > m_width) && ((i % m_width) < (m_width - 1))) |
|
424 { |
|
425 dstVal |= (*(src+m_width)+*(src-m_width))/2 << 16 | |
|
426 *src << 8 | |
|
427 (*(src-1)+*(src+1))/2; |
|
428 } |
|
429 else |
|
430 { |
|
431 dstVal |= *(src+m_width) << 16 | |
|
432 *src << 8 | |
|
433 *(src - 1); |
|
434 } |
|
435 } |
|
436 } |
|
437 else { |
|
438 |
|
439 if (!(i & 1)) |
|
440 { |
|
441 /* G(R) */ |
|
442 if ((i < (m_width * (m_height - 1))) && ((i % m_width) > 0) ) |
|
443 { |
|
444 dstVal |= ((*(src - 1) + *(src + 1)) / 2) << 16 | |
|
445 *src << 8 | |
|
446 (*(src + m_width) + *(src - m_width)) / 2; |
|
447 } |
|
448 else |
|
449 { |
|
450 dstVal |= *(src + 1) << 16 | |
|
451 *src << 8 | |
|
452 *(src - m_width); |
|
453 } |
|
454 } |
|
455 else |
|
456 { |
|
457 /* R */ |
|
458 if (i < (m_width * (m_height - 1)) && ((i % m_width) < (m_width - 1)) ) |
|
459 { |
|
460 dstVal |= *src << 16 | |
|
461 (*(src-1)+*(src+1)+ *(src-m_width)+*(src+m_width))/4 << 8 | |
|
462 (*(src-m_width-1)+*(src-m_width+1)+ *(src+m_width-1)+*(src+m_width+1))/4; |
|
463 } |
|
464 else |
|
465 { |
|
466 dstVal |= *src << 16 | |
|
467 (*(src-1)+*(src-m_width))/2 << 8 | |
|
468 *(src-m_width-1); |
|
469 } |
|
470 } |
|
471 } |
|
472 |
|
473 *dst++ = dstVal; |
|
474 ++src; |
|
475 } |
|
476 |
|
477 return m_buf; |
|
478 } |
|
479 |
|
480 |
|