Fix 62B3 to use correct format decoding routines
[microdia.git] / microdia-decoder.c
blob4b49f345b5b1407c80d52ba63be53866afbb3aab
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, const int);
48 void raw6270_2RGB24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
49 struct microdia_coord *view, const int hflip, const int vflip, const int factor);
50 void raw6270_2BGR24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
51 struct microdia_coord *view, const int hflip, const int vflip, const int factor);
52 void microdia_getraw(uint8_t *, uint8_t *, int);
54 void microdia_raw2i420(uint8_t *, uint8_t *, struct microdia_coord *,
55 struct microdia_coord *, const int, const int, const int);
56 void microdia_raw2bgr24(uint8_t *, uint8_t *, struct microdia_coord *,
57 struct microdia_coord *, const int, const int, const int);
60 void microdia_correct_brightness(uint8_t *, const int, const int,
61 const int, int);
64 /**
65 * @brief Decompress a frame
67 * This function permits to decompress a frame from the video stream.
69 * @param dev Device structure
70 * @param buffer Image data
72 * @returns 0 if all is OK
74 int microdia_decompress(struct usb_microdia *dev,
75 struct v4l2_buffer *buffer)
77 int factor;
78 int vflip;
79 int hflip;
80 int ret = 0;
82 void *data;
83 void *image;
85 if (dev == NULL) {
86 ret = -EFAULT;
87 goto done;
90 if (dev->flip_detect) {
91 dev->flip_detect(dev);
94 if (dev->set_hvflip) {
95 hflip = 0;
96 vflip = 0;
97 } else {
98 hflip = dev->vsettings.hflip;
99 vflip = dev->vsettings.vflip;
102 image = dev->queue.scratch;
104 data = dev->queue.mem + buffer->m.offset;
105 memcpy(image, data, MICRODIA_FRAME_SIZE);
107 switch (dev->resolution) {
108 case MICRODIA_80x60:
109 factor = 8;
110 break;
112 case MICRODIA_160x120:
113 factor = 4;
114 break;
116 case MICRODIA_320x240:
117 factor = 2;
118 break;
120 case MICRODIA_640x480:
121 case MICRODIA_800x600:
122 case MICRODIA_1024x768:
123 case MICRODIA_1280x1024:
124 factor = 1;
125 break;
127 default:
128 ret = -EFAULT;
129 goto done;
132 switch (dev->vsettings.format.pixelformat) {
133 case V4L2_PIX_FMT_RGB24:
134 if (dev->webcam_model == MICRODIA_6270
135 || dev->webcam_model == MICRODIA_627B
136 || dev->webcam_model == MICRODIA_6288
137 || dev->webcam_model == MICRODIA_62B3) {
138 raw6270_2RGB24(image, data, &dev->image, &dev->view,
139 hflip, vflip, factor);
141 break;
142 case V4L2_PIX_FMT_BGR24:
143 if (dev->webcam_model == MICRODIA_6270
144 || dev->webcam_model == MICRODIA_627B
145 || dev->webcam_model == MICRODIA_6288
146 || dev->webcam_model == MICRODIA_62B3) {
147 raw6270_2BGR24(image, data, &dev->image, &dev->view,
148 hflip, vflip, factor);
149 } else {
150 microdia_raw2bgr24(image, data, &dev->image, &dev->view,
151 hflip, vflip, factor);
153 break;
154 case V4L2_PIX_FMT_YUV420:
155 if (dev->webcam_model == MICRODIA_6270
156 || dev->webcam_model == MICRODIA_627B
157 || dev->webcam_model == MICRODIA_6288
158 || dev->webcam_model == MICRODIA_62B3) {
159 raw6270_2i420(image, data, &dev->image, &dev->view,
160 hflip, vflip, factor);
161 } else {
162 microdia_raw2i420(image, data, &dev->image, &dev->view,
163 hflip, vflip, factor);
165 break;
166 case V4L2_PIX_FMT_YUYV:
167 default:
168 break;
171 buffer->bytesused = dev->vsettings.format.sizeimage;
172 done:
173 return ret;
178 * @brief Correct the brightness of an image.
180 * This function permits to correct the brightness of an image.
182 * @param img Buffer to RGB/YUV data
183 * @param width Width of frame
184 * @param height Height of frame
185 * @param brightness Brightness correction
186 * @param palette
188 * @retval rgb Buffer to RGB/YUV data
190 void microdia_correct_brightness(uint8_t *img, const int width, const int height,
191 const int brightness, int palette)
193 int i;
194 int x;
195 int depth;
198 switch (palette) {
199 case V4L2_PIX_FMT_RGB24:
200 case V4L2_PIX_FMT_BGR24:
201 depth = 24;
202 case V4L2_PIX_FMT_RGB32:
203 case V4L2_PIX_FMT_BGR32:
204 depth = (depth == 24) ? 3 : 4;
206 if (brightness >= 32767) {
207 x = (brightness - 32767) / 256;
209 for (i = 0; i < (width * height * depth); i++) {
210 if ((*(img + i) + (unsigned char) x) > 255)
211 *(img + i) = 255;
212 else
213 *(img + i) += (unsigned char) x;
216 else {
217 x = (32767 - brightness) / 256;
219 for (i = 0; i < (width * height * depth); i++) {
220 if ((unsigned char) x > *(img + i))
221 *(img + i) = 0;
222 else
223 *(img + i) -= (unsigned char) x;
227 break;
229 case V4L2_PIX_FMT_UYVY:
230 depth = 2;
232 if (brightness >= 32767) {
233 x = (brightness - 32767) / 256;
235 for (i = 1; i < (width * height * depth); i=i+depth) {
236 if ((*(img + i) + (unsigned char) x) > 255)
237 *(img + i) = 255;
238 else
239 *(img + i) += (unsigned char) x;
242 else {
243 x = (32767 - brightness) / 256;
245 for (i = 1; i < (width * height * depth); i=i+depth) {
246 if ((unsigned char) x > *(img + i))
247 *(img + i) = 0;
248 else
249 *(img + i) -= (unsigned char) x;
253 break;
255 case V4L2_PIX_FMT_YUYV:
256 depth = 2;
258 if (brightness >= 32767) {
259 x = (brightness - 32767) / 256;
261 for (i = 0; i < (width * height * depth); i=i+depth) {
262 if ((*(img + i) + (unsigned char) x) > 255)
263 *(img + i) = 255;
264 else
265 *(img + i) += (unsigned char) x;
268 else {
269 x = (32767 - brightness) / 256;
271 for (i = 0; i < (width * height * depth); i=i+depth) {
272 if ((unsigned char) x > *(img + i))
273 *(img + i) = 0;
274 else
275 *(img + i) -= (unsigned char) x;
279 break;
284 /**
285 * @brief This function permits to get the raw data. (without treatments)
287 * @param bayer Buffer with the bayer data
288 * @param size Length of bayer buffer
290 * @retval raw Buffer with the data from video sensor
292 void microdia_getraw(uint8_t *bayer, uint8_t *raw,
293 int size) {
294 memcpy(raw, bayer, size);
297 /* Table to translate Y offset to UV offset */
298 static int UVTranslate[32] = {0, 1, 2, 3,
299 8, 9, 10, 11,
300 16, 17, 18, 19,
301 24, 25, 26, 27,
302 4, 5, 6, 7,
303 12, 13, 14, 15,
304 20, 21, 22, 23,
305 28, 29, 30, 31};
307 static int Y_coords_624x[128][2] = {
308 { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 0}, { 5, 0}, { 6, 0}, { 7, 0},
309 { 0, 1}, { 1, 1}, { 2, 1}, { 3, 1}, { 4, 1}, { 5, 1}, { 6, 1}, { 7, 1},
310 { 0, 2}, { 1, 2}, { 2, 2}, { 3, 2}, { 4, 2}, { 5, 2}, { 6, 2}, { 7, 2},
311 { 0, 3}, { 1, 3}, { 2, 3}, { 3, 3}, { 4, 3}, { 5, 3}, { 6, 3}, { 7, 3},
313 { 0, 4}, { 1, 4}, { 2, 4}, { 3, 4}, { 4, 4}, { 5, 4}, { 6, 4}, { 7, 4},
314 { 0, 5}, { 1, 5}, { 2, 5}, { 3, 5}, { 4, 5}, { 5, 5}, { 6, 5}, { 7, 5},
315 { 0, 6}, { 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6}, { 7, 6},
316 { 0, 7}, { 1, 7}, { 2, 7}, { 3, 7}, { 4, 7}, { 5, 7}, { 6, 7}, { 7, 7},
318 { 8, 0}, { 9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0},
319 { 8, 1}, { 9, 1}, {10, 1}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1},
320 { 8, 2}, { 9, 2}, {10, 2}, {11, 2}, {12, 2}, {13, 2}, {14, 2}, {15, 2},
321 { 8, 3}, { 9, 3}, {10, 3}, {11, 3}, {12, 3}, {13, 3}, {14, 3}, {15, 3},
323 { 8, 4}, { 9, 4}, {10, 4}, {11, 4}, {12, 4}, {13, 4}, {14, 4}, {15, 4},
324 { 8, 5}, { 9, 5}, {10, 5}, {11, 5}, {12, 5}, {13, 5}, {14, 5}, {15, 5},
325 { 8, 6}, { 9, 6}, {10, 6}, {11, 6}, {12, 6}, {13, 6}, {14, 6}, {15, 6},
326 { 8, 7}, { 9, 7}, {10, 7}, {11, 7}, {12, 7}, {13, 7}, {14, 7}, {15, 7}
329 void microdia_raw2bgr24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
330 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
332 int i = 0, x = 0, y = 0;
333 unsigned char *buf = raw;
334 unsigned char *buf3 = rgb;
335 int fwidth, fheight;
337 fwidth = image->x / factor;
338 fheight = image->y / factor;
340 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
341 int tile = 0;
342 for (tile = 0; tile < 4; tile++) {
343 int subX = 0;
344 int subY = 0;
345 for (subY = 0; subY < 4; subY++) {
346 for (subX = 0; subX < 8; subX++) {
347 int subI = i + tile * 32 + 8 * subY + subX;
348 int subU = i + 128 + UVTranslate[tile * 8 + 4 * (subY >> 1) + (subX >> 1)];
349 int subV = subU + 32;
351 int relX = x + (((tile == 0) || (tile == 1)) ? 0 : 8) + subX; //tile 0, 1 to into left comumn
352 int relY = y + (((tile == 0) || (tile == 2)) ? 0 : 4) + subY; //tile 0, 2 go into top row
354 if (hflip) {
355 relX = image->x - relX;
357 if (vflip) {
358 relY = image->y - relY;
361 relX /= factor;
362 relY /= factor;
364 relX += (view->x - fwidth) >> 1;
365 relY += (view->y - fheight) >> 1;
366 if ((relX < view->x) && (relY < view->y)) {
367 unsigned char *ptr;
368 int c, d, e;
369 c = buf[subI] - 16;
370 d = buf[subU] - 128;
371 e = buf[subV] - 128;
373 ptr = buf3 + relY * view->x * 3 + relX * 3;
374 *ptr = CLIP((298 * c + 516 * d + 128) >> 8, 0, 255);
375 ptr++;
376 *ptr = CLIP((298 * c - 100 * d - 208 * e + 128) >> 8, 0, 255);
377 ptr++;
378 *ptr = CLIP((298 * c + 409 * e + 128) >> 8, 0, 255);
384 i += 192;
385 x += 16;
386 if (x >= image->x) {
387 x = 0;
388 y += 8;
393 void microdia_raw2i420(uint8_t *raw, uint8_t *i420, struct microdia_coord *image,
394 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
396 int i = 0, x = 0, y = 0, j, relX, relY, x_div2, y_div2;
397 unsigned char *buf = raw, *ptr;
398 unsigned char *buf3 = i420;
399 int fwidth = image->x / factor, fheight = image->y / factor;
400 int view_size = view->x * view->y;
401 int view_size_div4 = view_size >> 2;
402 int x_padding = (view->x - fwidth) >> 1;
403 int y_padding = (view->y - fheight) >> 1;
404 int x_padding_div2 = x_padding >> 1;
405 int y_padding_div2 = y_padding >> 1;
406 int image_x_div2 = image->x >> 1;
407 int image_y_div2 = image->y >> 1;
408 int view_x_div2 = view->x >> 1;
410 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
411 for (j = 0; j < 128; j++) {
412 relX = x + Y_coords_624x[j][0];
413 relY = y + Y_coords_624x[j][1];
414 if (hflip)
415 relX = image->x - relX - 1;
416 if (vflip)
417 relY = image->y - relY - 1;
419 switch (factor) {
421 case 1:
422 break;
423 case 2:
424 relX >>= 1;
425 relY >>= 1;
426 break;
427 case 4:
428 relX >>= 2;
429 relY >>= 2;
430 break;
431 case 8:
432 relX >>= 3;
433 relY >>= 3;
434 break;
435 default:
436 relX /= factor;
437 relY /= factor;
438 break;
441 relX += x_padding;
442 relY += y_padding;
444 if ((relX < view->x) && (relY < view->y)) {
445 ptr = buf3 + relY * view->x + relX;
446 *ptr = buf[i + j];
450 x_div2 = x >> 1;
451 y_div2 = y >> 1;
452 for (j = 0; j < 32; j++) {
453 relX = (x_div2) + (j & 0x07);
454 relY = (y_div2) + (j >> 3);
455 if (hflip)
456 relX = image_x_div2 - relX - 1;
457 if (vflip)
458 relY = image_y_div2 - relY - 1;
460 relX += x_padding_div2;
461 relY += y_padding_div2;
463 switch (factor) {
465 case 1:
466 break;
467 case 2:
468 relX >>= 1;
469 relY >>= 1;
470 break;
471 case 4:
472 relX >>= 2;
473 relY >>= 2;
474 break;
475 case 8:
476 relX >>= 3;
477 relY >>= 3;
478 break;
479 default:
480 relX /= factor;
481 relY /= factor;
482 break;
485 if ((relX < view->x) && (relY < view->y)) {
486 ptr = buf3 + view_size +
487 relY * (view_x_div2) + relX;
488 *ptr = buf[i + 128 + j];
489 ptr += view_size_div4;
490 *ptr = buf[i + 160 + j];
495 i += 192;
496 x += 16;
497 if (x >= image->x) {
498 x = 0;
499 y += 8;
505 /**
507 * @brief This function permits to convert an image from 6270 raw format to i420
508 * @param raw Buffer with the bayer data
509 * @param image Size of image
510 * @param view Size of view
511 * @param hflip Horizontal flip - not implemented
512 * @param vflip Vertical flip - not implemented
513 * @param factor Factor of redimensioning - not used factor is recalculate to do any non standard transformations
515 * @retval i420 Buffer with the i420 data
516 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
517 y - repeated 640 times for 640x480
518 First 1280 bytes is maybe dumy ***FIX ME***
521 void raw6270_2i420(uint8_t *raw, uint8_t *i420, struct microdia_coord *image,
522 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
524 int i, j, YIndex = 0, UVIndex = 0;
525 unsigned char *y, *u, *v;
526 uint8_t *buf;
527 int hshift, vshift;
528 //For fast calculations
529 int x_div_2,y_div_2;
530 //Skip first 1280 bytes strange dummy bytes
531 raw+=1280;
533 x_div_2=image->x / 2; //for fast calculation if x=640 x_div_2=320
534 y_div_2=image->y / 2; //for fast calculation if y=480 y_div_4=240
535 buf=raw;
536 y = i420;
537 u = i420 + view->x * view->y;
538 v = i420 + view->x * view->y + (view->x >> 1) * (view->y >> 1);
540 hshift = view->x - (image->x / factor);
541 hshift >>= 1;
542 vshift = view->y - (image->y / factor);
543 vshift >>= 1;
545 YIndex = vshift * view->x + hshift;
546 UVIndex = (vshift >> 1) * (view->x >> 1) + (hshift >> 1);
547 //we skipped 1280 bytes, it's almost two lines
548 for (i = 0; i < y_div_2 - 1; i++) {
549 for (j = 0; j < x_div_2; j ++) {
550 u[UVIndex] = *buf;
551 buf++;
552 v[UVIndex] = *buf;
553 buf++;
554 y[YIndex] = *buf;
555 buf++;
556 YIndex += ((j * 2) % factor) == 0 ? 1 : 0;
557 y[YIndex] = *buf;
558 buf++;
559 YIndex += ((j * 2 + 1) % factor) == 0 ? 1 : 0;
560 UVIndex += (j % factor) == 0 ? 1 : 0;
562 YIndex -= hshift;
563 YIndex -= (image->x / factor);
564 if ((i * 2) % factor == 0) YIndex += view->x + hshift;
565 else YIndex += hshift;
567 for (j = 0; j < image->x; j++) {
568 y[YIndex] = *buf;
569 buf++;
570 YIndex += (j % factor) == 0 ? 1 : 0;
572 YIndex -= hshift;
573 YIndex -= (image->x / factor);
574 if ((i * 2 + 1) % factor == 0) YIndex += view->x + hshift;
575 else YIndex += hshift;
577 UVIndex -= (hshift >> 1);
578 UVIndex -= x_div_2 / factor;
579 if (i % factor == 0) UVIndex += (view->x >> 1) + (hshift >> 1);
580 else UVIndex += (hshift >> 1);
584 /**
586 * @brief This function permits to convert an image from 6270 raw format to BGR24
587 * @param raw Buffer with the bayer data
588 * @param image Size of image
589 * @param view Size of view
590 * @param hflip Horizontal flip - not implemented yet
591 * @param vflip Vertical flip - not implemented yet
592 * @param factor Factor of redimensioning - not used factor is recalculate to do any non standard transformations
594 * @retval rgb Buffer with the rgb data
595 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
596 y - repeated 640 times for 640x480
597 First 1280 bytes is maybe dumy ***FIX ME***
600 void raw6270_2BGR24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
601 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
603 int i, j, incX;
604 //Maybe is not necesery to use long variables but I not sure in this moment
605 long y11,y12,y21,y22, u, v,y,C,D,E;
606 long ScaleIncX,ScaleIncY;
607 long pointerIncX,pointerIncY;
608 uint8_t *bufUVYY;
609 uint8_t *bufY;
610 uint8_t *out_row1;
611 uint8_t *out_row2;
613 //For fast calculations
614 int x_div_2,y_div_2;
615 //Skip first 1280 bytes strange dummy bytes
616 raw+=1280;
618 x_div_2=image->x / 2; //for fast calculation if x=640 x_div_2=320
619 y_div_2=image->y / 2; //for fast calculation if y=480 y_div_4=240
620 incX=3*view->x; //Incrementation koeficient for next row
621 bufUVYY=raw;
622 bufY=raw+2*image->x;
624 //Because I can't use float ratio is multiply by 1000 then 1000 is equal of increment image (X or Y) with 1
625 ScaleIncX=(1000*view->x)/image->x;
626 ScaleIncY=(1000*view->y)/image->y;
629 out_row1=rgb;
630 out_row2=out_row1+incX;
631 //we skipped 1280 bytes, it's almost two lines
632 pointerIncY=1000;
633 for (i = 0; i < y_div_2-1; i++) {
634 pointerIncX=1000;
635 for (j = 0; j < x_div_2; j ++) {
637 pointerIncX+=ScaleIncX;
639 u=(unsigned char)(*bufUVYY);
640 bufUVYY++;
641 v=(unsigned char)(*bufUVYY);
642 bufUVYY++;
643 y11=(unsigned char)(*bufUVYY);
644 bufUVYY++;
645 y12=(unsigned char)(*bufUVYY);
646 bufUVYY++;
647 y21=(unsigned char)(*bufY);
648 bufY++;
649 y22=(unsigned char)(*bufY);
650 bufY++;
652 if((pointerIncX>999)&&(pointerIncY>499)){
653 pointerIncX-=1001;
654 y=y11;
655 C = y - 16;
656 D = u - 128;
657 E = v - 128;
659 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
660 out_row1++;
661 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
662 out_row1++;
663 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
664 out_row1++;
666 y=y12;
668 C = y - 16;
669 D = u - 128;
670 E = v - 128;
673 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
674 out_row1++;
675 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
676 out_row1++;
677 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
678 out_row1++;
681 //Second row of stream is displayed only if image is greath than half
682 if(ScaleIncY>501)
684 y=y21;
686 C = y - 16;
687 D = u - 128;
688 E = v - 128;
690 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
691 out_row2++;
692 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
693 out_row2++;
694 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
695 out_row2++;
697 y=y22;
699 C = y - 16;
700 D = u - 128;
701 E = v - 128;
703 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
704 out_row2++;
705 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
706 out_row2++;
707 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
708 out_row2++;
712 //this comparation can be optimized and moved in if((pointerIncX>999)&&(pointerIncY>499))
713 if(pointerIncY>499)
714 pointerIncY-=500;
715 //Use 2 rows only if vertical ratio > 0.5 (increment is ratio*1000)
716 if(ScaleIncY>501)
718 out_row1=out_row1+incX;
719 out_row2=out_row2+incX;
723 pointerIncY+= ScaleIncY;
724 bufUVYY=bufUVYY+image->x;
725 bufY=bufY+2*image->x;
731 /**
733 * @brief This function permits to convert an image from 6270 raw format to RGB24
734 * @brief The same function as convert to BGR24 but only B and R is change order
735 * @param raw Buffer with the bayer data
736 * @param image Size of image
737 * @param view Size of view
738 * @param hflip Horizontal flip
739 * @param vflip Vertical flip
740 * @param factor Factor of redimensioning
742 * @retval rgb Buffer with the rgb data
743 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
744 y - repeated 640 times for 640x480
745 First 1280 bytes is maybe dumy ***FIX ME***
748 void raw6270_2RGB24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
749 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
751 int i, j, incX;
752 //Maybe is not necesery to use long variables but I not sure in this moment
753 long y11,y12,y21,y22, u, v,y,C,D,E;
754 long ScaleIncX,ScaleIncY;
755 long pointerIncX,pointerIncY;
756 uint8_t *bufUVYY;
757 uint8_t *bufY;
758 uint8_t *out_row1;
759 uint8_t *out_row2;
761 //For fast calculations
762 int x_div_2,y_div_2;
763 //Skip first 1280 bytes strange dummy bytes
764 raw+=1280;
766 x_div_2=image->x / 2; //for fast calculation if x=640 x_div_2=320
767 y_div_2=image->y / 2; //for fast calculation if y=480 y_div_4=240
768 incX=3*view->x;
769 bufUVYY=raw;
770 bufY=raw+2*image->x;
772 //Because I can't use float ratio is multiply by 1000 then 1000 is equal of increment image (X or Y) with 1
773 ScaleIncX=(1000*view->x)/image->x;
774 ScaleIncY=(1000*view->y)/image->y;
777 out_row1=rgb;
778 out_row2=out_row1+incX;
779 //we skipped 1280 bytes, it's almost two lines
780 pointerIncY=1000;
781 for (i = 0; i < y_div_2-1; i++) {
782 pointerIncX=1000;
783 for (j = 0; j < x_div_2; j ++) {
785 pointerIncX+=ScaleIncX;
787 u=(unsigned char)(*bufUVYY);
788 bufUVYY++;
789 v=(unsigned char)(*bufUVYY);
790 bufUVYY++;
791 y11=(unsigned char)(*bufUVYY);
792 bufUVYY++;
793 y12=(unsigned char)(*bufUVYY);
794 bufUVYY++;
795 y21=(unsigned char)(*bufY);
796 bufY++;
797 y22=(unsigned char)(*bufY);
798 bufY++;
800 if((pointerIncX>999)&&(pointerIncY>499)){
801 pointerIncX-=1001;
802 y=y11;
803 C = y - 16;
804 D = u - 128;
805 E = v - 128;
807 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
808 out_row1++;
809 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
810 out_row1++;
811 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
812 out_row1++;
814 y=y12;
816 C = y - 16;
817 D = u - 128;
818 E = v - 128;
821 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
822 out_row1++;
823 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
824 out_row1++;
825 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
826 out_row1++;
829 //Second row of stream is displayed only if image is greath than half
830 if(ScaleIncY>501)
832 y=y21;
834 C = y - 16;
835 D = u - 128;
836 E = v - 128;
838 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
839 out_row2++;
840 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
841 out_row2++;
842 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
843 out_row2++;
845 y=y22;
847 C = y - 16;
848 D = u - 128;
849 E = v - 128;
851 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
852 out_row2++;
853 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
854 out_row2++;
855 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
856 out_row2++;
860 //this comparation can be optimized and moved in if((pointerIncX>999)&&(pointerIncY>499))
861 if(pointerIncY>499)
862 pointerIncY-=500;
863 //Use 2 rows only if vertical ratio > 0.5 (increment is ratio*1000)
864 if(ScaleIncY>501)
866 out_row1=out_row1+incX;
867 out_row2=out_row2+incX;
871 pointerIncY+= ScaleIncY;
872 bufUVYY=bufUVYY+image->x;
873 bufY=bufY+2*image->x;