Minimizing 624f_start_stream
[microdia.git] / microdia-decoder.c
blob2913a23ea9906e5200a4a015e8a9509f7369bafc
1 /**
2 * @file microdia-decoder.c
3 * @author Nicolas VIVIEN
4 * @date 2008-02-01
5 * @version v0.0.0
7 * @brief Driver for Microdia USB video camera
9 * @note Copyright (C) Nicolas VIVIEN
11 * @par Licences
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/version.h>
32 #include <linux/errno.h>
33 #include <linux/slab.h>
34 #include <linux/kref.h>
36 #include <linux/usb.h>
37 #include <media/v4l2-common.h>
39 #include "microdia.h"
42 #define MAX(a, b) ((a) > (b) ? (a) : (b))
43 #define MIN(a, b) ((a) < (b) ? (a) : (b))
44 #define CLIP(a, low, high) MAX((low), MIN((high), (a)))
46 void raw6270_2i420(uint8_t *, uint8_t *, struct microdia_coord *,
47 struct microdia_coord *, const int, const int,
48 const int);
50 void raw6270_2RGB24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
51 struct microdia_coord *view, const int hflip,
52 const int vflip, const int factor);
54 void raw6270_2BGR24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
55 struct microdia_coord *view, const int hflip,
56 const int vflip, const int factor);
58 void microdia_getraw(uint8_t *, uint8_t *, int);
60 void microdia_raw2i420(uint8_t *, uint8_t *, struct microdia_coord *,
61 struct microdia_coord *, const int, const int,
62 const int);
64 void microdia_raw2bgr24(uint8_t *, uint8_t *, struct microdia_coord *,
65 struct microdia_coord *, const int, const int,
66 const int);
68 void microdia_correct_brightness(uint8_t *, const int, const int,
69 const int, int);
71 /**
72 * @brief Decompress a frame
74 * This function permits to decompress a frame from the video stream.
76 * @param dev Device structure
77 * @param buffer Image data
79 * @returns 0 if all is OK
81 int microdia_decompress(struct usb_microdia *dev, struct v4l2_buffer *buffer)
83 int factor;
84 int vflip;
85 int hflip;
86 int ret = 0;
88 void *data;
89 void *image;
91 if (dev == NULL) {
92 ret = -EFAULT;
93 goto done;
96 if (dev->flip_detect)
97 dev->flip_detect(dev);
99 if (dev->set_hvflip) {
100 hflip = 0;
101 vflip = 0;
102 } else {
103 hflip = dev->vsettings.hflip;
104 vflip = dev->vsettings.vflip;
107 image = dev->queue.scratch;
109 data = dev->queue.mem + buffer->m.offset;
110 memcpy(image, data, MICRODIA_FRAME_SIZE);
112 switch (dev->resolution) {
113 case MICRODIA_80x60:
114 factor = 8;
115 break;
117 case MICRODIA_160x120:
118 factor = 4;
119 break;
121 case MICRODIA_320x240:
122 factor = 2;
123 break;
125 case MICRODIA_640x480:
126 case MICRODIA_800x600:
127 case MICRODIA_1024x768:
128 case MICRODIA_1280x1024:
129 factor = 1;
130 break;
132 default:
133 ret = -EFAULT;
134 goto done;
137 switch (dev->vsettings.format.pixelformat) {
138 case V4L2_PIX_FMT_RGB24:
139 if (dev->webcam_model ==
140 CAMERA_MODEL(USB_0C45_VID, USB_6270_PID) ||
141 dev->webcam_model ==
142 CAMERA_MODEL(USB_0C45_VID, USB_627B_PID) ||
143 dev->webcam_model ==
144 CAMERA_MODEL(USB_0C45_VID, USB_6288_PID) ||
145 dev->webcam_model ==
146 CAMERA_MODEL(USB_0C45_VID, USB_62B3_PID) ||
147 dev->webcam_model ==
148 CAMERA_MODEL(USB_145F_VID, USB_013D_PID)) {
149 raw6270_2RGB24(image, data, &dev->image, &dev->view,
150 hflip, vflip, factor);
152 break;
153 case V4L2_PIX_FMT_BGR24:
154 if (dev->webcam_model ==
155 CAMERA_MODEL(USB_0C45_VID, USB_6270_PID) ||
156 dev->webcam_model ==
157 CAMERA_MODEL(USB_0C45_VID, USB_627B_PID) ||
158 dev->webcam_model ==
159 CAMERA_MODEL(USB_0C45_VID, USB_6288_PID) ||
160 dev->webcam_model ==
161 CAMERA_MODEL(USB_0C45_VID, USB_62B3_PID) ||
162 dev->webcam_model ==
163 CAMERA_MODEL(USB_145F_VID, USB_013D_PID)) {
164 raw6270_2BGR24(image, data, &dev->image, &dev->view,
165 hflip, vflip, factor);
166 } else {
167 microdia_raw2bgr24(image, data, &dev->image, &dev->view,
168 hflip, vflip, factor);
170 break;
171 case V4L2_PIX_FMT_YUV420:
172 if (dev->webcam_model ==
173 CAMERA_MODEL(USB_0C45_VID, USB_6270_PID) ||
174 dev->webcam_model ==
175 CAMERA_MODEL(USB_0C45_VID, USB_627B_PID) ||
176 dev->webcam_model ==
177 CAMERA_MODEL(USB_0C45_VID, USB_6288_PID) ||
178 dev->webcam_model ==
179 CAMERA_MODEL(USB_0C45_VID, USB_62B3_PID) ||
180 dev->webcam_model ==
181 CAMERA_MODEL(USB_145F_VID, USB_013D_PID)) {
182 raw6270_2i420(image, data, &dev->image, &dev->view,
183 hflip, vflip, factor);
184 } else {
185 microdia_raw2i420(image, data, &dev->image, &dev->view,
186 hflip, vflip, factor);
188 break;
189 case V4L2_PIX_FMT_YUYV:
190 default:
191 break;
194 buffer->bytesused = dev->vsettings.format.sizeimage;
195 done:
196 return ret;
201 * @brief Correct the brightness of an image.
203 * This function permits to correct the brightness of an image.
205 * @param img Buffer to RGB/YUV data
206 * @param width Width of frame
207 * @param height Height of frame
208 * @param brightness Brightness correction
209 * @param palette
211 * @retval rgb Buffer to RGB/YUV data
213 void microdia_correct_brightness(uint8_t *img, const int width,
214 const int height, const int brightness,
215 int palette)
217 int i;
218 int x;
219 int depth;
221 switch (palette) {
222 case V4L2_PIX_FMT_RGB24:
223 case V4L2_PIX_FMT_BGR24:
224 depth = 24;
225 case V4L2_PIX_FMT_RGB32:
226 case V4L2_PIX_FMT_BGR32:
227 depth = (depth == 24) ? 3 : 4;
229 if (brightness >= 32767) {
230 x = (brightness - 32767) / 256;
232 for (i = 0; i < (width * height * depth); i++) {
233 if ((*(img + i) + (unsigned char) x) > 255)
234 *(img + i) = 255;
235 else
236 *(img + i) += (unsigned char) x;
238 } else {
239 x = (32767 - brightness) / 256;
240 for (i = 0; i < (width * height * depth); i++) {
241 if ((unsigned char) x > *(img + i))
242 *(img + i) = 0;
243 else
244 *(img + i) -= (unsigned char) x;
247 break;
249 case V4L2_PIX_FMT_UYVY:
250 depth = 2;
252 if (brightness >= 32767) {
253 x = (brightness - 32767) / 256;
255 for (i = 1; i < (width * height * depth); i += depth) {
256 if ((*(img + i) + (unsigned char) x) > 255)
257 *(img + i) = 255;
258 else
259 *(img + i) += (unsigned char) x;
261 } else {
262 x = (32767 - brightness) / 256;
264 for (i = 1; i < (width * height * depth); i += depth) {
265 if ((unsigned char) x > *(img + i))
266 *(img + i) = 0;
267 else
268 *(img + i) -= (unsigned char) x;
272 break;
274 case V4L2_PIX_FMT_YUYV:
275 depth = 2;
277 if (brightness >= 32767) {
278 x = (brightness - 32767) / 256;
280 for (i = 0; i < (width * height * depth); i += depth) {
281 if ((*(img + i) + (unsigned char) x) > 255)
282 *(img + i) = 255;
283 else
284 *(img + i) += (unsigned char) x;
286 } else {
287 x = (32767 - brightness) / 256;
289 for (i = 0; i < (width * height * depth); i += depth) {
290 if ((unsigned char) x > *(img + i))
291 *(img + i) = 0;
292 else
293 *(img + i) -= (unsigned char) x;
297 break;
303 * @brief This function permits to get the raw data. (without treatments)
305 * @param bayer Buffer with the bayer data
306 * @param size Length of bayer buffer
308 * @retval raw Buffer with the data from video sensor
310 void microdia_getraw(uint8_t *bayer, uint8_t *raw,
311 int size) {
312 memcpy(raw, bayer, size);
315 /* Table to translate Y offset to UV offset */
316 static int UVTranslate[32] = {
317 0, 1, 2, 3,
318 8, 9, 10, 11,
319 16, 17, 18, 19,
320 24, 25, 26, 27,
321 4, 5, 6, 7,
322 12, 13, 14, 15,
323 20, 21, 22, 23,
324 28, 29, 30, 31
327 static int Y_coords_624x[128][2] = {
328 { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 0}, { 5, 0}, { 6, 0}, { 7, 0},
329 { 0, 1}, { 1, 1}, { 2, 1}, { 3, 1}, { 4, 1}, { 5, 1}, { 6, 1}, { 7, 1},
330 { 0, 2}, { 1, 2}, { 2, 2}, { 3, 2}, { 4, 2}, { 5, 2}, { 6, 2}, { 7, 2},
331 { 0, 3}, { 1, 3}, { 2, 3}, { 3, 3}, { 4, 3}, { 5, 3}, { 6, 3}, { 7, 3},
333 { 0, 4}, { 1, 4}, { 2, 4}, { 3, 4}, { 4, 4}, { 5, 4}, { 6, 4}, { 7, 4},
334 { 0, 5}, { 1, 5}, { 2, 5}, { 3, 5}, { 4, 5}, { 5, 5}, { 6, 5}, { 7, 5},
335 { 0, 6}, { 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6}, { 7, 6},
336 { 0, 7}, { 1, 7}, { 2, 7}, { 3, 7}, { 4, 7}, { 5, 7}, { 6, 7}, { 7, 7},
338 { 8, 0}, { 9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0},
339 { 8, 1}, { 9, 1}, {10, 1}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1},
340 { 8, 2}, { 9, 2}, {10, 2}, {11, 2}, {12, 2}, {13, 2}, {14, 2}, {15, 2},
341 { 8, 3}, { 9, 3}, {10, 3}, {11, 3}, {12, 3}, {13, 3}, {14, 3}, {15, 3},
343 { 8, 4}, { 9, 4}, {10, 4}, {11, 4}, {12, 4}, {13, 4}, {14, 4}, {15, 4},
344 { 8, 5}, { 9, 5}, {10, 5}, {11, 5}, {12, 5}, {13, 5}, {14, 5}, {15, 5},
345 { 8, 6}, { 9, 6}, {10, 6}, {11, 6}, {12, 6}, {13, 6}, {14, 6}, {15, 6},
346 { 8, 7}, { 9, 7}, {10, 7}, {11, 7}, {12, 7}, {13, 7}, {14, 7}, {15, 7}
349 void microdia_raw2bgr24(uint8_t *raw, uint8_t *rgb,
350 struct microdia_coord *image,
351 struct microdia_coord *view, const int hflip,
352 const int vflip, const int factor)
354 int i = 0, x = 0, y = 0;
355 unsigned char *buf = raw;
356 unsigned char *buf3 = rgb;
357 int fwidth, fheight;
359 fwidth = image->x / factor;
360 fheight = image->y / factor;
362 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
363 int tile = 0;
364 for (tile = 0; tile < 4; tile++) {
365 int subX = 0;
366 int subY = 0;
367 for (subY = 0; subY < 4; subY++) {
368 for (subX = 0; subX < 8; subX++) {
369 int subI = i + tile * 32 + 8 * subY + subX;
370 int subU = i + 128 + UVTranslate[tile * 8 + 4 * (subY >> 1) + (subX >> 1)];
371 int subV = subU + 32;
373 int relX = x + (((tile == 0) || (tile == 1)) ? 0 : 8) + subX; /* tile 0, 1 to into left column*/
374 int relY = y + (((tile == 0) || (tile == 2)) ? 0 : 4) + subY; /* tile 0, 2 go into top row */
376 if (hflip)
377 relX = image->x - relX;
378 if (vflip)
379 relY = image->y - relY;
381 relX /= factor;
382 relY /= factor;
384 relX += (view->x - fwidth) >> 1;
385 relY += (view->y - fheight) >> 1;
386 if ((relX < view->x) && (relY < view->y)) {
387 unsigned char *ptr;
388 int c, d, e;
389 c = buf[subI] - 16;
390 d = buf[subU] - 128;
391 e = buf[subV] - 128;
393 ptr = buf3 + relY * view->x * 3 + relX * 3;
394 *ptr = CLIP((298 * c + 516 * d + 128) >> 8, 0, 255);
395 ptr++;
396 *ptr = CLIP((298 * c - 100 * d - 208 * e + 128) >> 8, 0, 255);
397 ptr++;
398 *ptr = CLIP((298 * c + 409 * e + 128) >> 8, 0, 255);
404 i += 192;
405 x += 16;
406 if (x >= image->x) {
407 x = 0;
408 y += 8;
413 void microdia_raw2i420(uint8_t *raw, uint8_t *i420,
414 struct microdia_coord *image,
415 struct microdia_coord *view, const int hflip,
416 const int vflip, const int factor)
418 int i = 0, x = 0, y = 0, j, relX, relY, x_div2, y_div2;
419 unsigned char *buf = raw, *ptr;
420 unsigned char *buf3 = i420;
421 int fwidth = image->x / factor, fheight = image->y / factor;
422 int view_size = view->x * view->y;
423 int view_size_div4 = view_size >> 2;
424 int x_padding = (view->x - fwidth) >> 1;
425 int y_padding = (view->y - fheight) >> 1;
426 int x_padding_div2 = x_padding >> 1;
427 int y_padding_div2 = y_padding >> 1;
428 int image_x_div2 = image->x >> 1;
429 int image_y_div2 = image->y >> 1;
430 int view_x_div2 = view->x >> 1;
432 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
433 for (j = 0; j < 128; j++) {
434 relX = x + Y_coords_624x[j][0];
435 relY = y + Y_coords_624x[j][1];
436 if (hflip)
437 relX = image->x - relX - 1;
438 if (vflip)
439 relY = image->y - relY - 1;
441 switch (factor) {
443 case 1:
444 break;
445 case 2:
446 relX >>= 1;
447 relY >>= 1;
448 break;
449 case 4:
450 relX >>= 2;
451 relY >>= 2;
452 break;
453 case 8:
454 relX >>= 3;
455 relY >>= 3;
456 break;
457 default:
458 relX /= factor;
459 relY /= factor;
460 break;
463 relX += x_padding;
464 relY += y_padding;
466 if ((relX < view->x) && (relY < view->y)) {
467 ptr = buf3 + relY * view->x + relX;
468 *ptr = buf[i + j];
472 x_div2 = x >> 1;
473 y_div2 = y >> 1;
474 for (j = 0; j < 32; j++) {
475 relX = (x_div2) + (j & 0x07);
476 relY = (y_div2) + (j >> 3);
477 if (hflip)
478 relX = image_x_div2 - relX - 1;
479 if (vflip)
480 relY = image_y_div2 - relY - 1;
482 relX += x_padding_div2;
483 relY += y_padding_div2;
485 switch (factor) {
487 case 1:
488 break;
489 case 2:
490 relX >>= 1;
491 relY >>= 1;
492 break;
493 case 4:
494 relX >>= 2;
495 relY >>= 2;
496 break;
497 case 8:
498 relX >>= 3;
499 relY >>= 3;
500 break;
501 default:
502 relX /= factor;
503 relY /= factor;
504 break;
507 if ((relX < view->x) && (relY < view->y)) {
508 ptr = buf3 + view_size +
509 relY * (view_x_div2) + relX;
510 *ptr = buf[i + 128 + j];
511 ptr += view_size_div4;
512 *ptr = buf[i + 160 + j];
517 i += 192;
518 x += 16;
519 if (x >= image->x) {
520 x = 0;
521 y += 8;
528 * @brief This function permits to convert an image from 6270 raw format to i420
529 * @param raw Buffer with the bayer data
530 * @param image Size of image
531 * @param view Size of view
532 * @param hflip Horizontal flip - not implemented
533 * @param vflip Vertical flip - not implemented
534 * @param factor Factor of redimensioning - not used factor is recalculate
535 to do any non standard transformations
537 * @retval i420 Buffer with the i420 data
538 * Format of stream is uvyy,uvyy - repeated 320 times for 640x480
539 y - repeated 640 times for 640x480
540 First 1280 bytes is maybe dummy ***FIXME***
543 void raw6270_2i420(uint8_t *raw, uint8_t *i420, struct microdia_coord *image,
544 struct microdia_coord *view, const int hflip,
545 const int vflip, const int factor)
547 int i, j, YIndex = 0, UVIndex = 0;
548 unsigned char *y, *u, *v;
549 uint8_t *buf;
550 int hshift, vshift;
551 /* For fast calculations */
552 int x_div_2, y_div_2;
553 /* Skip first 1280 bytes strange dummy bytes */
554 raw += 1280;
556 x_div_2 = image->x / 2; /* for fast calculation if x=640 x_div_2=320 */
557 y_div_2 = image->y / 2; /* for fast calculation if y=480 y_div_4=240 */
558 buf = raw;
559 y = i420;
560 u = i420 + view->x * view->y;
561 v = i420 + view->x * view->y + (view->x >> 1) * (view->y >> 1);
563 hshift = view->x - (image->x / factor);
564 hshift >>= 1;
565 vshift = view->y - (image->y / factor);
566 vshift >>= 1;
568 YIndex = vshift * view->x + hshift;
569 UVIndex = (vshift >> 1) * (view->x >> 1) + (hshift >> 1);
570 /* we skipped 1280 bytes, it's almost two lines */
571 for (i = 0; i < y_div_2 - 1; i++) {
572 for (j = 0; j < x_div_2; j++) {
573 u[UVIndex] = *buf;
574 buf++;
575 v[UVIndex] = *buf;
576 buf++;
577 y[YIndex] = *buf;
578 buf++;
579 YIndex += ((j * 2) % factor) == 0 ? 1 : 0;
580 y[YIndex] = *buf;
581 buf++;
582 YIndex += ((j * 2 + 1) % factor) == 0 ? 1 : 0;
583 UVIndex += (j % factor) == 0 ? 1 : 0;
585 YIndex -= hshift;
586 YIndex -= (image->x / factor);
587 if ((i * 2) % factor == 0)
588 YIndex += view->x + hshift;
589 else
590 YIndex += hshift;
592 for (j = 0; j < image->x; j++) {
593 y[YIndex] = *buf;
594 buf++;
595 YIndex += (j % factor) == 0 ? 1 : 0;
597 YIndex -= hshift;
598 YIndex -= (image->x / factor);
599 if ((i * 2 + 1) % factor == 0)
600 YIndex += view->x + hshift;
601 else
602 YIndex += hshift;
604 UVIndex -= (hshift >> 1);
605 UVIndex -= x_div_2 / factor;
606 if (i % factor == 0)
607 UVIndex += (view->x >> 1) + (hshift >> 1);
608 else
609 UVIndex += (hshift >> 1);
615 * @brief This function permits to convert an image from 6270 rawformat to BGR24
616 * @param raw Buffer with the bayer data
617 * @param image Size of image
618 * @param view Size of view
619 * @param hflip Horizontal flip - not implemented yet
620 * @param vflip Vertical flip - not implemented yet
621 * @param factor Factor of redimensioning - not used factor is recalculate
622 to do any non standard transformations
624 * @retval rgb Buffer with the rgb data
625 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
626 y - repeated 640 times for 640x480
627 First 1280 bytes is maybe dumy ***FIXME***
630 void raw6270_2BGR24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
631 struct microdia_coord *view, const int hflip,
632 const int vflip, const int factor)
634 int i, j, incX;
635 /* Maybe is not necesery to use long variables but I not sure in this moment */
636 long y11, y12, y21, y22, u, v, y, C, D, E;
637 long ScaleIncX, ScaleIncY;
638 long pointerIncX, pointerIncY;
639 uint8_t *bufUVYY;
640 uint8_t *bufY;
641 uint8_t *out_row1;
642 uint8_t *out_row2;
644 /* For fast calculations*/
645 int x_div_2, y_div_2;
646 /* Skip first 1280 bytes strange dummy bytes */
647 raw += 1280;
649 x_div_2 = image->x / 2; /* for fast calculation if x=640 x_div_2=320 */
650 y_div_2 = image->y / 2; /* for fast calculation if y=480 y_div_4=240 */
651 incX = 3 * view->x; /* Incrementation koeficient for next row*/
652 bufUVYY = raw;
653 bufY = raw + 2 * image->x;
656 // Because I can't use float ratio is multiply by 1000
657 // then 1000 is equal of increment image (X or Y) with 1
659 ScaleIncX = (1000 * view->x) / image->x;
660 ScaleIncY = (1000 * view->y) / image->y;
662 out_row1 = rgb;
663 out_row2 = out_row1 + incX;
664 /* we skipped 1280 bytes, it's almost two lines*/
665 pointerIncY = 1000;
666 for (i = 0; i < y_div_2-1; i++) {
667 pointerIncX = 1000;
668 for (j = 0; j < x_div_2; j++) {
669 pointerIncX += ScaleIncX;
671 u = (unsigned char)(*bufUVYY);
672 bufUVYY++;
674 v = (unsigned char)(*bufUVYY);
675 bufUVYY++;
677 y11 = (unsigned char)(*bufUVYY);
678 bufUVYY++;
680 y12 = (unsigned char)(*bufUVYY);
681 bufUVYY++;
683 y21 = (unsigned char)(*bufY);
684 bufY++;
686 y22 = (unsigned char)(*bufY);
687 bufY++;
689 if ((pointerIncX > 999) && (pointerIncY > 499)) {
690 pointerIncX -= 1001;
691 y = y11;
692 C = y - 16;
693 D = u - 128;
694 E = v - 128;
696 *out_row1 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
697 out_row1++;
698 *out_row1 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
699 out_row1++;
700 *out_row1 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
701 out_row1++;
703 y = y12;
705 C = y - 16;
706 D = u - 128;
707 E = v - 128;
710 *out_row1 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
711 out_row1++;
712 *out_row1 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
713 out_row1++;
714 *out_row1 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
715 out_row1++;
718 // Second row of stream is displayed only
719 // if image is greath than half
721 if (ScaleIncY > 501) {
722 y = y21;
724 C = y - 16;
725 D = u - 128;
726 E = v - 128;
728 *out_row2 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
729 out_row2++;
730 *out_row2 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
731 out_row2++;
732 *out_row2 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
733 out_row2++;
735 y = y22;
737 C = y - 16;
738 D = u - 128;
739 E = v - 128;
741 *out_row2 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
742 out_row2++;
743 *out_row2 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
744 out_row2++;
745 *out_row2 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
746 out_row2++;
751 // this comparation can be optimized and moved in
752 // if((pointerIncX>999)&&(pointerIncY>499))
754 if (pointerIncY > 499)
755 pointerIncY -= 500;
757 // Use 2 rows only if
758 // vertical ratio > 0.5 (increment is ratio*1000)
760 if (ScaleIncY > 501) {
761 out_row1 = out_row1 + incX;
762 out_row2 = out_row2 + incX;
765 pointerIncY += ScaleIncY;
766 bufUVYY = bufUVYY + image->x;
767 bufY = bufY + 2 * image->x;
773 * @brief This function permits to convert an image from 6270 rawformat to RGB24
774 * @brief The same function as convert to BGR24 but only B and R is change order
775 * @param raw Buffer with the bayer data
776 * @param image Size of image
777 * @param view Size of view
778 * @param hflip Horizontal flip
779 * @param vflip Vertical flip
780 * @param factor Factor of redimensioning
782 * @retval rgb Buffer with the rgb data
783 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
784 y - repeated 640 times for 640x480
785 First 1280 bytes is maybe dumy ***FIXME***
788 void raw6270_2RGB24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
789 struct microdia_coord *view, const int hflip,
790 const int vflip, const int factor)
792 int i, j, incX;
793 /* Maybe is not necesery to use long variables but I not sure in this moment */
794 long y11, y12, y21, y22, u, v, y, C, D, E;
795 long ScaleIncX, ScaleIncY;
796 long pointerIncX, pointerIncY;
797 uint8_t *bufUVYY;
798 uint8_t *bufY;
799 uint8_t *out_row1;
800 uint8_t *out_row2;
802 /* For fast calculations */
803 int x_div_2, y_div_2;
804 /* Skip first 1280 bytes strange dummy bytes */
805 raw += 1280;
807 x_div_2 = image->x / 2; /* for fast calculation if x=640 x_div_2=320 */
808 y_div_2 = image->y / 2; /* for fast calculation if y=480 y_div_4=240 */
809 incX = 3 * view->x;
810 bufUVYY = raw;
811 bufY = raw + 2 * image->x;
814 // Because I can't use float ratio is multiply by 1000 then
815 // 1000 is equal of increment image (X or Y) with 1
817 ScaleIncX = (1000*view->x) / image->x;
818 ScaleIncY = (1000*view->y) / image->y;
820 out_row1 = rgb;
821 out_row2 = out_row1 + incX;
822 /* we skipped 1280 bytes, it's almost two lines */
823 pointerIncY = 1000;
824 for (i = 0; i < y_div_2-1; i++) {
825 pointerIncX = 1000;
826 for (j = 0; j < x_div_2; j++) {
827 pointerIncX += ScaleIncX;
829 u = (unsigned char)(*bufUVYY);
830 bufUVYY++;
832 v = (unsigned char)(*bufUVYY);
833 bufUVYY++;
835 y11 = (unsigned char)(*bufUVYY);
836 bufUVYY++;
838 y12 = (unsigned char)(*bufUVYY);
839 bufUVYY++;
841 y21 = (unsigned char)(*bufY);
842 bufY++;
844 y22 = (unsigned char)(*bufY);
845 bufY++;
847 if ((pointerIncX > 999) && (pointerIncY > 499)) {
848 pointerIncX -= 1001;
849 y = y11;
850 C = y - 16;
851 D = u - 128;
852 E = v - 128;
854 *out_row1 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
855 out_row1++;
856 *out_row1 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
857 out_row1++;
858 *out_row1 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
859 out_row1++;
861 y = y12;
863 C = y - 16;
864 D = u - 128;
865 E = v - 128;
867 *out_row1 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
868 out_row1++;
869 *out_row1 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
870 out_row1++;
871 *out_row1 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
872 out_row1++;
875 // Second row of stream is displayed only
876 // if image is greath than half
878 if (ScaleIncY > 501) {
879 y = y21;
881 C = y - 16;
882 D = u - 128;
883 E = v - 128;
885 *out_row2 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
886 out_row2++;
887 *out_row2 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
888 out_row2++;
889 *out_row2 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
890 out_row2++;
892 y = y22;
894 C = y - 16;
895 D = u - 128;
896 E = v - 128;
898 *out_row2 = CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
899 out_row2++;
900 *out_row2 = CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
901 out_row2++;
902 *out_row2 = CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
903 out_row2++;
908 // this comparation can be optimized and moved in
909 // if((pointerIncX>999)&&(pointerIncY>499))
911 if (pointerIncY > 499)
912 pointerIncY -= 500;
913 /* Use 2 rows only if vertical ratio > 0.5 (increment is ratio*1000) */
914 if (ScaleIncY > 501) {
915 out_row1 = out_row1 + incX;
916 out_row2 = out_row2 + incX;
919 pointerIncY += ScaleIncY;
920 bufUVYY = bufUVYY + image->x;
921 bufY = bufY + 2 * image->x;