Added support for O_NONBLOCK in DQBUF ioctl
[microdia.git] / microdia-bayer.c
blob5fc95e42b46e6f4b4cf336e5ee8ed86380b3f8a9
1 /**
2 * @file microdia-bayer.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
27 * @par SubVersion
28 * $Date: $
29 * $Revision: $
30 * $Author: $
31 * $HeadURL: $
34 #include <linux/module.h>
35 #include <linux/init.h>
36 #include <linux/kernel.h>
37 #include <linux/version.h>
38 #include <linux/errno.h>
39 #include <linux/slab.h>
40 #include <linux/kref.h>
42 #include <linux/usb.h>
43 #include <media/v4l2-common.h>
45 #include "microdia.h"
48 #define MAX(a,b) ((a)>(b)?(a):(b))
49 #define MIN(a,b) ((a)<(b)?(a):(b))
50 #define CLIP(a,low,high) MAX((low),MIN((high),(a)))
52 //Add by Boris Borisov decode by Vasily Khoruzhick adapt to V4L by Brian Johnson
53 void raw6270_2i420(uint8_t *, uint8_t *, struct microdia_coord *,
54 struct microdia_coord *, const int, const int, const int);
55 void microdia_getraw(uint8_t *, uint8_t *, int);
57 void microdia_raw2i420(uint8_t *, uint8_t *, struct microdia_coord *,
58 struct microdia_coord *, const int, const int, const int);
59 void microdia_raw2bgr24(uint8_t *, uint8_t *, struct microdia_coord *,
60 struct microdia_coord *, const int, const int, const int);
61 void microdia_b2rgb24(uint8_t *, uint8_t *,
62 struct microdia_coord *, struct microdia_coord *,
63 const int, const int, const int);
64 void microdia_b2rgb32(uint8_t *, uint8_t *,
65 struct microdia_coord *, struct microdia_coord *,
66 const int, const int, const int);
67 void microdia_b2bgr24(uint8_t *, uint8_t *,
68 struct microdia_coord *, struct microdia_coord *,
69 const int, const int, const int);
70 void microdia_b2bgr32(uint8_t *, uint8_t *,
71 struct microdia_coord *, struct microdia_coord *,
72 const int, const int, const int);
74 void microdia_b2uyvy(uint8_t *, uint8_t *,
75 struct microdia_coord *, struct microdia_coord *,
76 const int, const int, const int);
77 void microdia_b2yuyv(uint8_t *, uint8_t *,
78 struct microdia_coord *, struct microdia_coord *,
79 const int, const int, const int);
82 void microdia_correct_brightness(uint8_t *, const int, const int,
83 const int, int, int);
86 static signed short microdia_yuv_interp[256][8] = {
87 {0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,1,0,0,0,1,0,0},{0,1,0,0,0,1,-1,0},
88 {1,2,0,0,-1,2,-1,0},{1,2,0,0,-1,2,-2,0},{1,3,0,-1,-1,3,-2,0},{2,3,0,-1,-2,3,-2,0},
89 {2,4,0,-1,-2,4,-3,0},{2,5,1,-1,-2,4,-3,0},{2,5,1,-1,-3,5,-4,0},{3,6,1,-1,-3,5,-4,0},
90 {3,6,1,-2,-3,6,-5,0},{3,7,1,-2,-4,6,-5,-1},{4,7,1,-2,-4,7,-5,-1},{4,8,1,-2,-4,7,-6,-1},
91 {4,9,1,-2,-5,8,-6,-1},{5,9,1,-2,-5,8,-7,-1},{5,10,2,-3,-5,9,-7,-1},{5,10,2,-3,-6,9,-7,-1},
92 {5,11,2,-3,-6,10,-8,-1},{6,11,2,-3,-6,10,-8,-1},{6,12,2,-3,-7,11,-9,-1},{6,13,2,-3,-7,11,-9,-1},
93 {7,13,2,-4,-7,12,-10,-1},{7,14,2,-4,-8,12,-10,-2},{7,14,2,-4,-8,13,-10,-2},{8,15,3,-4,-8,13,-11,-2},
94 {8,15,3,-4,-9,14,-11,-2},{8,16,3,-4,-9,14,-12,-2},{8,17,3,-5,-9,15,-12,-2},{9,17,3,-5,-10,15,-12,-2},
95 {9,18,3,-5,-10,16,-13,-2},{9,18,3,-5,-10,16,-13,-2},{10,19,3,-5,-11,17,-14,-2},{10,19,3,-5,-11,17,-14,-2},
96 {10,20,4,-6,-11,18,-15,-2},{11,20,4,-6,-12,18,-15,-3},{11,21,4,-6,-12,19,-15,-3},{11,22,4,-6,-12,19,-16,-3},
97 {11,22,4,-6,-13,20,-16,-3},{12,23,4,-6,-13,20,-17,-3},{12,23,4,-7,-13,21,-17,-3},{12,24,4,-7,-14,21,-18,-3},
98 {13,24,5,-7,-14,22,-18,-3},{13,25,5,-7,-14,22,-18,-3},{13,26,5,-7,-15,23,-19,-3},{14,26,5,-7,-15,23,-19,-3},
99 {14,27,5,-8,-15,24,-20,-3},{14,27,5,-8,-16,24,-20,-3},{14,28,5,-8,-16,25,-20,-4},{15,28,5,-8,-16,25,-21,-4},
100 {15,29,5,-8,-17,26,-21,-4},{15,30,6,-8,-17,26,-22,-4},{16,30,6,-9,-17,27,-22,-4},{16,31,6,-9,-18,27,-23,-4},
101 {16,31,6,-9,-18,28,-23,-4},{17,32,6,-9,-18,28,-23,-4},{17,32,6,-9,-19,29,-24,-4},{17,33,6,-9,-19,29,-24,-4},
102 {17,34,6,-10,-19,30,-25,-4},{18,34,6,-10,-20,30,-25,-4},{18,35,7,-10,-20,31,-25,-5},{18,35,7,-10,-20,31,-26,-5},
103 {19,36,7,-10,-21,32,-26,-5},{19,36,7,-10,-21,32,-27,-5},{19,37,7,-11,-21,33,-27,-5},{20,37,7,-11,-22,33,-28,-5},
104 {20,38,7,-11,-22,34,-28,-5},{20,39,7,-11,-22,34,-28,-5},{20,39,7,-11,-23,35,-29,-5},{21,40,8,-11,-23,35,-29,-5},
105 {21,40,8,-12,-23,36,-30,-5},{21,41,8,-12,-24,36,-30,-5},{22,41,8,-12,-24,37,-30,-6},{22,42,8,-12,-24,37,-31,-6},
106 {22,43,8,-12,-25,38,-31,-6},{23,43,8,-12,-25,38,-32,-6},{23,44,8,-13,-25,39,-32,-6},{23,44,9,-13,-26,39,-33,-6},
107 {23,45,9,-13,-26,40,-33,-6},{24,45,9,-13,-26,40,-33,-6},{24,46,9,-13,-27,41,-34,-6},{24,47,9,-14,-27,41,-34,-6},
108 {25,47,9,-14,-27,42,-35,-6},{25,48,9,-14,-28,42,-35,-6},{25,48,9,-14,-28,43,-36,-6},{26,49,9,-14,-28,43,-36,-7},
109 {26,49,10,-14,-29,44,-36,-7},{26,50,10,-15,-29,44,-37,-7},{26,51,10,-15,-29,45,-37,-7},{27,51,10,-15,-30,45,-38,-7},
110 {27,52,10,-15,-30,46,-38,-7},{27,52,10,-15,-30,46,-38,-7},{28,53,10,-15,-31,47,-39,-7},{28,53,10,-16,-31,47,-39,-7},
111 {28,54,10,-16,-31,48,-40,-7},{29,54,11,-16,-32,48,-40,-7},{29,55,11,-16,-32,49,-41,-7},{29,56,11,-16,-32,49,-41,-8},
112 {29,56,11,-16,-33,50,-41,-8},{30,57,11,-17,-33,50,-42,-8},{30,57,11,-17,-33,51,-42,-8},{30,58,11,-17,-34,51,-43,-8},
113 {31,58,11,-17,-34,52,-43,-8},{31,59,11,-17,-34,52,-43,-8},{31,60,12,-17,-35,53,-44,-8},{31,60,12,-18,-35,53,-44,-8},
114 {32,61,12,-18,-35,54,-45,-8},{32,61,12,-18,-36,54,-45,-8},{32,62,12,-18,-36,55,-46,-8},{33,62,12,-18,-36,55,-46,-9},
115 {33,63,12,-18,-37,56,-46,-9},{33,64,12,-19,-37,56,-47,-9},{34,64,12,-19,-37,57,-47,-9},{34,65,13,-19,-38,57,-48,-9},
116 {34,65,13,-19,-38,58,-48,-9},{34,66,13,-19,-38,58,-48,-9},{35,66,13,-19,-39,59,-49,-9},{35,67,13,-20,-39,59,-49,-9},
117 {35,68,13,-20,-39,60,-50,-9},{36,68,13,-20,-40,60,-50,-9},{36,69,13,-20,-40,61,-51,-9},{36,69,14,-20,-40,61,-51,-9},
118 {37,70,14,-20,-41,62,-51,-10},{37,70,14,-21,-41,62,-52,-10},{37,71,14,-21,-41,63,-52,-10},{37,72,14,-21,-42,63,-53,-10},
119 {38,72,14,-21,-42,64,-53,-10},{38,73,14,-21,-42,64,-54,-10},{38,73,14,-21,-43,65,-54,-10},{39,74,14,-22,-43,65,-54,-10},
120 {39,74,15,-22,-43,66,-55,-10},{39,75,15,-22,-44,66,-55,-10},{40,75,15,-22,-44,67,-56,-10},{40,76,15,-22,-44,67,-56,-10},
121 {40,77,15,-22,-45,68,-56,-11},{40,77,15,-23,-45,68,-57,-11},{41,78,15,-23,-45,69,-57,-11},{41,78,15,-23,-46,69,-58,-11},
122 {41,79,15,-23,-46,70,-58,-11},{42,79,16,-23,-46,70,-59,-11},{42,80,16,-23,-47,71,-59,-11},{42,81,16,-24,-47,71,-59,-11},
123 {43,81,16,-24,-47,72,-60,-11},{43,82,16,-24,-48,72,-60,-11},{43,82,16,-24,-48,73,-61,-11},{43,83,16,-24,-48,73,-61,-11},
124 {44,83,16,-24,-49,74,-61,-12},{44,84,16,-25,-49,74,-62,-12},{44,85,17,-25,-49,75,-62,-12},{45,85,17,-25,-50,75,-63,-12},
125 {45,86,17,-25,-50,76,-63,-12},{45,86,17,-25,-50,76,-64,-12},{46,87,17,-25,-51,77,-64,-12},{46,87,17,-26,-51,77,-64,-12},
126 {46,88,17,-26,-51,78,-65,-12},{46,89,17,-26,-52,78,-65,-12},{47,89,18,-26,-52,79,-66,-12},{47,90,18,-26,-52,79,-66,-12},
127 {47,90,18,-26,-53,80,-66,-13},{48,91,18,-27,-53,80,-67,-13},{48,91,18,-27,-53,81,-67,-13},{48,92,18,-27,-54,81,-68,-13},
128 {49,92,18,-27,-54,82,-68,-13},{49,93,18,-27,-54,82,-69,-13},{49,94,18,-28,-54,83,-69,-13},{49,94,19,-28,-55,83,-69,-13},
129 {50,95,19,-28,-55,84,-70,-13},{50,95,19,-28,-55,84,-70,-13},{50,96,19,-28,-56,85,-71,-13},{51,96,19,-28,-56,85,-71,-13},
130 {51,97,19,-29,-56,86,-72,-13},{51,98,19,-29,-57,86,-72,-14},{52,98,19,-29,-57,87,-72,-14},{52,99,19,-29,-57,87,-73,-14},
131 {52,99,20,-29,-58,88,-73,-14},{52,100,20,-29,-58,88,-74,-14},{53,100,20,-30,-58,89,-74,-14},{53,101,20,-30,-59,89,-74,-14},
132 {53,102,20,-30,-59,90,-75,-14},{54,102,20,-30,-59,90,-75,-14},{54,103,20,-30,-60,91,-76,-14},{54,103,20,-30,-60,91,-76,-14},
133 {55,104,20,-31,-60,92,-77,-14},{55,104,21,-31,-61,92,-77,-15},{55,105,21,-31,-61,93,-77,-15},{55,106,21,-31,-61,93,-78,-15},
134 {56,106,21,-31,-62,94,-78,-15},{56,107,21,-31,-62,94,-79,-15},{56,107,21,-32,-62,95,-79,-15},{57,108,21,-32,-63,95,-79,-15},
135 {57,108,21,-32,-63,96,-80,-15},{57,109,22,-32,-63,96,-80,-15},{58,109,22,-32,-64,97,-81,-15},{58,110,22,-32,-64,97,-81,-15},
136 {58,111,22,-33,-64,98,-82,-15},{58,111,22,-33,-65,98,-82,-16},{59,112,22,-33,-65,99,-82,-16},{59,112,22,-33,-65,99,-83,-16},
137 {59,113,22,-33,-66,100,-83,-16},{60,113,22,-33,-66,100,-84,-16},{60,114,23,-34,-66,101,-84,-16},{60,115,23,-34,-67,101,-84,-16},
138 {60,115,23,-34,-67,102,-85,-16},{61,116,23,-34,-67,102,-85,-16},{61,116,23,-34,-68,103,-86,-16},{61,117,23,-34,-68,103,-86,-16},
139 {62,117,23,-35,-68,104,-87,-16},{62,118,23,-35,-69,104,-87,-16},{62,119,23,-35,-69,105,-87,-17},{63,119,24,-35,-69,105,-88,-17},
140 {63,120,24,-35,-70,106,-88,-17},{63,120,24,-35,-70,106,-89,-17},{63,121,24,-36,-70,107,-89,-17},{64,121,24,-36,-71,107,-90,-17},
141 {64,122,24,-36,-71,108,-90,-17},{64,123,24,-36,-71,108,-90,-17},{65,123,24,-36,-72,109,-91,-17},{65,124,24,-36,-72,109,-91,-17},
142 {65,124,25,-37,-72,110,-92,-17},{66,125,25,-37,-73,110,-92,-17},{66,125,25,-37,-73,111,-92,-18},{66,126,25,-37,-73,111,-93,-18},
143 {66,127,25,-37,-74,112,-93,-18},{67,127,25,-37,-74,112,-94,-18},{67,128,25,-38,-74,113,-94,-18},{67,128,25,-38,-75,113,-95,-18},
144 {68,129,25,-38,-75,114,-95,-18},{68,129,26,-38,-75,114,-95,-18},{68,130,26,-38,-76,115,-96,-18},{69,130,26,-38,-76,115,-96,-18},
145 {69,131,26,-39,-76,116,-97,-18},{69,132,26,-39,-77,116,-97,-18},{69,132,26,-39,-77,117,-97,-19},{70,133,26,-39,-77,117,-98,-19},
146 {70,133,26,-39,-78,118,-98,-19},{70,134,27,-39,-78,118,-99,-19},{71,134,27,-40,-78,119,-99,-19},{71,135,27,-40,-79,119,-100,-19},
147 {71,136,27,-40,-79,120,-100,-19},{72,136,27,-40,-79,120,-100,-19},{72,137,27,-40,-80,121,-101,-19},{72,137,27,-40,-80,121,-101,-19},
148 {72,138,27,-41,-80,122,-102,-19},{73,138,27,-41,-81,122,-102,-19},{73,139,28,-41,-81,123,-103,-19},{73,140,28,-41,-81,123,-103,-20},
149 {74,140,28,-41,-82,124,-103,-20},{74,141,28,-42,-82,124,-104,-20},{74,141,28,-42,-82,125,-104,-20},{75,142,28,-42,-83,125,-105,-20},
150 {75,142,28,-42,-83,126,-105,-20},{75,143,28,-42,-83,126,-105,-20},{75,144,28,-42,-84,127,-106,-20},{76,144,29,-43,-84,127,-106,-20}
154 /**
155 * @brief Decompress a frame
157 * This function permits to decompress a frame from the video stream.
159 * @param dev Device structure
161 * @returns 0 if all is OK
163 int microdia_decompress(struct usb_microdia *dev)
165 int size;
166 int factor;
168 void *data;
169 void *image;
170 struct microdia_frame_buf *framebuf;
172 if (dev == NULL)
173 return -EFAULT;
175 framebuf = dev->read_frame;
177 if (framebuf == NULL)
178 return -EFAULT;
180 image = dev->image_data;
181 image += dev->images[dev->fill_image].offset;
183 data = framebuf->data;
184 size = framebuf->filled;
186 switch (dev->resolution) {
187 case MICRODIA_80x60:
188 factor = 8;
189 break;
191 /*case MICRODIA_128x96:
192 factor = 5;
193 break;*/
195 case MICRODIA_160x120:
196 factor = 4;
197 break;
199 /*case MICRODIA_213x160:
200 factor = 3;
201 break;*/
203 case MICRODIA_320x240:
204 factor = 2;
205 break;
207 case MICRODIA_640x480:
208 factor = 1;
209 break;
211 case MICRODIA_800x600:
212 factor = 1;
213 break;
215 case MICRODIA_1024x768:
216 factor = 1;
217 break;
219 case MICRODIA_1280x1024:
220 factor = 1;
221 break;
223 default:
224 return -EFAULT;
228 switch (dev->vsettings.palette) {
229 case MICRODIA_PALETTE_BGR24:
230 microdia_raw2bgr24(data, image, &dev->image, &dev->view,
231 dev->vsettings.hflip, dev->vsettings.vflip, factor);
232 break;
234 /*case MICRODIA_PALETTE_RGB32:
235 microdia_b2rgb32(data, image, &dev->image, &dev->view,
236 dev->vsettings.hflip, dev->vsettings.vflip, factor);
237 break;
239 case MICRODIA_PALETTE_BGR24:
240 microdia_b2bgr24(data, image, &dev->image, &dev->view,
241 dev->vsettings.hflip, dev->vsettings.vflip, factor);
242 break;
244 case MICRODIA_PALETTE_BGR32:
245 microdia_b2bgr32(data, image, &dev->image, &dev->view,
246 dev->vsettings.hflip, dev->vsettings.vflip, factor);
247 break;
249 case MICRODIA_PALETTE_UYVY:
250 microdia_b2uyvy(data, image, &dev->image, &dev->view,
251 dev->vsettings.hflip, dev->vsettings.vflip, factor);
252 break;
254 case MICRODIA_PALETTE_YUYV:
255 microdia_b2yuyv(data, image, &dev->image, &dev->view,
256 dev->vsettings.hflip, dev->vsettings.vflip, factor);
257 break;
259 case MICRODIA_PALETTE_I420:
260 if(dev->webcam_model == MICRODIA_6270
261 || dev->webcam_model == MICRODIA_627B)
263 raw6270_2i420(data, image, &dev->image, &dev->view,
264 dev->vsettings.hflip, dev->vsettings.vflip, factor);
265 } else
267 microdia_raw2i420(data, image, &dev->image, &dev->view,
268 dev->vsettings.hflip, dev->vsettings.vflip, factor);
270 break;
271 default:
272 microdia_getraw(data, image, size);
273 break;
276 //microdia_correct_brightness(image, dev->view.x, dev->view.y,
277 // dev->vsettings.brightness, dev->vsettings.palette, dev->vsettings.depth);
279 return 0;
284 * @brief Correct the brightness of an image.
286 * This function permits to correct the brightness of an image.
288 * @param img Buffer to RGB/YUV data
289 * @param width Width of frame
290 * @param height Height of frame
291 * @param brightness Brightness correction
292 * @param palette
293 * @param depth Color depth
295 * @retval rgb Buffer to RGB/YUV data
297 void microdia_correct_brightness(uint8_t *img, const int width, const int height,
298 const int brightness, int palette, int depth)
300 int i;
301 int x;
304 switch (palette) {
305 case MICRODIA_PALETTE_RGB24:
306 case MICRODIA_PALETTE_BGR24:
307 case MICRODIA_PALETTE_RGB32:
308 case MICRODIA_PALETTE_BGR32:
309 depth = (depth == 24) ? 3 : 4;
311 if (brightness >= 32767) {
312 x = (brightness - 32767) / 256;
314 for (i = 0; i < (width * height * depth); i++) {
315 if ((*(img + i) + (unsigned char) x) > 255)
316 *(img + i) = 255;
317 else
318 *(img + i) += (unsigned char) x;
321 else {
322 x = (32767 - brightness) / 256;
324 for (i = 0; i < (width * height * depth); i++) {
325 if ((unsigned char) x > *(img + i))
326 *(img + i) = 0;
327 else
328 *(img + i) -= (unsigned char) x;
332 break;
334 case MICRODIA_PALETTE_UYVY:
335 depth = 2;
337 if (brightness >= 32767) {
338 x = (brightness - 32767) / 256;
340 for (i = 1; i < (width * height * depth); i=i+depth) {
341 if ((*(img + i) + (unsigned char) x) > 255)
342 *(img + i) = 255;
343 else
344 *(img + i) += (unsigned char) x;
347 else {
348 x = (32767 - brightness) / 256;
350 for (i = 1; i < (width * height * depth); i=i+depth) {
351 if ((unsigned char) x > *(img + i))
352 *(img + i) = 0;
353 else
354 *(img + i) -= (unsigned char) x;
358 break;
360 case MICRODIA_PALETTE_YUYV:
361 depth = 2;
363 if (brightness >= 32767) {
364 x = (brightness - 32767) / 256;
366 for (i = 0; i < (width * height * depth); i=i+depth) {
367 if ((*(img + i) + (unsigned char) x) > 255)
368 *(img + i) = 255;
369 else
370 *(img + i) += (unsigned char) x;
373 else {
374 x = (32767 - brightness) / 256;
376 for (i = 0; i < (width * height * depth); i=i+depth) {
377 if ((unsigned char) x > *(img + i))
378 *(img + i) = 0;
379 else
380 *(img + i) -= (unsigned char) x;
384 break;
389 /**
390 * @brief This function permits to get the raw data. (without treatments)
392 * @param bayer Buffer with the bayer data
393 * @param size Length of bayer buffer
395 * @retval raw Buffer with the data from video sensor
397 void microdia_getraw(uint8_t *bayer, uint8_t *raw,
398 int size) {
399 memcpy(raw, bayer, size);
402 void microdia_raw2bgr24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
403 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
405 int i = 0, x = 0, y = 0;
406 unsigned char *buf = raw;
407 unsigned char *buf3 = rgb;
408 int fwidth, fheight;
410 fwidth = image->x / factor;
411 fheight = image->y / factor;
413 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
414 int tile = 0;
415 for (tile = 0; tile < 4; tile++) {
416 int subX = 0;
417 int subY = 0;
418 for (subY = 0; subY < 4; subY++) {
419 for (subX = 0; subX < 8; subX++) {
420 int subI = i + tile * 32 + 8 * subY + subX;
421 int subU = i + 128 + tile * 8 + (subY >> 1) * 4 + (subX >> 1);
422 int subV = subU + 32;
424 int relX = x + (((tile == 0) || (tile == 1)) ? 0 : 8) + subX; //tile 0, 1 to into left comumn
425 int relY = y + (((tile == 0) || (tile == 2)) ? 0 : 4) + subY; //tile 0, 2 go into top row
428 if (hflip) {
429 relX = image->x - relX;
431 if (vflip) {
432 relY = image->y - relY;
435 relX /= factor;
436 relY /= factor;
438 relX += (view->x - fwidth) >> 1;
439 relY += (view->y - fheight) >> 1;
440 if ((relX < view->x) && (relY < view->y)) {
441 unsigned char *ptr;
442 int c, d, e;
443 c = buf[subI] - 16;
444 d = buf[subU] - 128;
445 e = buf[subV] - 128;
447 ptr = buf3 + relY * view->x * 3 + relX * 3;
448 *ptr = CLIP((298 * c + 516 * d + 128) >> 8, 0, 255);
449 ptr++;
450 *ptr = CLIP((298 * c - 100 * d - 208 * e + 128) >> 8, 0, 255);
451 ptr++;
452 *ptr = CLIP((298 * c + 409 * e + 128) >> 8, 0, 255);
458 i += 192;
459 x += 16;
460 if (x >= image->x) {
461 x = 0;
462 y += 8;
467 void microdia_raw2i420(uint8_t *raw, uint8_t *i420, struct microdia_coord *image,
468 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
470 int i = 0, x = 0, y = 0;
471 unsigned char *buf = raw;
472 unsigned char *buf3 = i420;
473 int fwidth, fheight;
475 fwidth = image->x / factor;
476 fheight = image->y / factor;
478 //printk(KERN_INFO "image: %d %d, view: %d %d factor: %d\n", image->x, image->y, view->x, view->y, factor);
480 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
481 int tile = 0;
482 for (tile = 0; tile < 4; tile++) {
483 int subX = 0;
484 int subY = 0;
485 for (subY = 0; subY < 4; subY++) {
486 for (subX = 0; subX < 8; subX++) {
487 int subI = i + tile * 32 + 8 * subY + subX;
488 int subU = i + 128 + tile * 8 + (subY >> 1) * 4 + (subX >> 1);
489 int subV = subU + 32;
491 int relX = x + (((tile == 0) || (tile == 1)) ? 0 : 8) + subX; //tile 0, 1 to into left comumn
492 int relY = y + (((tile == 0) || (tile == 2)) ? 0 : 4) + subY; //tile 0, 2 go into top row
495 if (hflip) {
496 relX = image->x - relX;
498 if (vflip) {
499 relY = image->y - relY;
502 relX /= factor;
503 relY /= factor;
505 relX += (view->x - fwidth) >> 1;
506 relY += (view->y - fheight) >> 1;
507 if ((relX < view->x) && (relY < view->y)) {
508 unsigned char *ptr;
510 ptr = buf3 + relY * view->x + relX;
511 *ptr = buf[subI];
512 ptr = (buf3 + (view->x * view->y) + (relY / 2) * (view->x / 2) + (relX / 2));
513 *ptr = buf[subU];
514 ptr = (buf3 + (view->x * view->y) + (view->x * view->y / 4) + (relY / 2) *
515 (view->x / 2)+ (relX / 2));
516 *ptr = buf[subV];
522 i += 192;
523 x += 16;
524 if (x >= image->x) {
525 x = 0;
526 y += 8;
532 //Add by Boris Borisov decode by Vasily Khoruzhick adapt to V4L by Brian Johnson
533 /**
534 * Add and optimize by Boris Borisov decode by Vasily Khoruzhick adapt to V4L by Brian Johnson
535 * @brief This function permits to convert an image from 6270 raw format to i420
536 * Add by Boris Borisov decode by Vasily Khoruzhick adapt to V4L by Brian Johnson
537 * @param raw Buffer with the bayer data
538 * @param image Size of image
539 * @param view Size of view
540 * @param hflip Horizontal flip
541 * @param vflip Vertical flip
542 * @param factor Factor of redimensioning
544 * @retval i420 Buffer with the i420 data
545 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
546 y - repeated 640 times for 640x480
547 First 1280 bytes is maybe dumy FIX ME
550 void raw6270_2i420(uint8_t *raw, uint8_t *i420, struct microdia_coord *image,
551 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
553 int i, j, YIndex = 0, UVIndex = 0;
554 unsigned char *y, *u, *v;
555 uint8_t *buf;
556 int hshift, vshift;
557 //For fast calculations
558 int x_div_2,y_div_2;
559 //Skip first 1280 bytes strange dummy bytes
560 raw+=1280;
562 x_div_2=image->x / 2; //for fast calculation if x=640 x_div_2=320
563 y_div_2=image->y / 2; //for fast calculation if y=480 y_div_4=240
564 buf=raw;
565 y = i420;
566 u = i420 + view->x * view->y;
567 v = i420 + view->x * view->y + (view->x >> 1) * (view->y >> 1);
569 hshift = view->x - (image->x / factor);
570 hshift >>= 1;
571 vshift = view->y - (image->y / factor);
572 vshift >>= 1;
574 YIndex = vshift * view->x + hshift;
575 UVIndex = (vshift >> 1) * (view->x >> 1) + (hshift >> 1);
576 //we skipped 1280 bytes, it's almost two lines
577 for (i = 0; i < y_div_2 - 1; i++) {
578 for (j = 0; j < x_div_2; j ++) {
579 u[UVIndex] = *buf;
580 buf++;
581 v[UVIndex] = *buf;
582 buf++;
583 y[YIndex] = *buf;
584 buf++;
585 YIndex += ((j * 2) % factor) == 0 ? 1 : 0;
586 y[YIndex] = *buf;
587 buf++;
588 YIndex += ((j * 2 + 1) % factor) == 0 ? 1 : 0;
589 UVIndex += (j % factor) == 0 ? 1 : 0;
591 YIndex -= hshift;
592 YIndex -= (image->x / factor);
593 if ((i * 2) % factor == 0) YIndex += view->x + hshift;
594 else YIndex += hshift;
596 for (j = 0; j < image->x; j++) {
597 y[YIndex] = *buf;
598 buf++;
599 YIndex += (j % factor) == 0 ? 1 : 0;
601 YIndex -= hshift;
602 YIndex -= (image->x / factor);
603 if ((i * 2 + 1) % factor == 0) YIndex += view->x + hshift;
604 else YIndex += hshift;
606 UVIndex -= (hshift >> 1);
607 UVIndex -= x_div_2 / factor;
608 if (i % factor == 0) UVIndex += (view->x >> 1) + (hshift >> 1);
609 else UVIndex += (hshift >> 1);
615 /**
616 * @brief This function permits to convert an image from bayer to RGB24
618 * @param bayer Buffer with the bayer data
619 * @param image Size of image
620 * @param view Size of view
621 * @param hflip Horizontal flip
622 * @param vflip Vertical flip
623 * @param factor Factor of redimensioning
625 * @retval rgb Buffer with the RGB data
627 void microdia_b2rgb24(uint8_t *bayer, uint8_t *rgb,
628 struct microdia_coord *image,
629 struct microdia_coord *view,
630 const int hflip, const int vflip,
631 const int factor) {
632 uint8_t *b;
634 int x, y; // Position in bayer image
635 int i, j; // Position in rgb image
637 int width = image->x;
638 int height = image->y;
640 int nwidth = width / factor;
641 int nheight = height / factor;
643 int offset;
644 int startx, stepx;
645 int starty, stepy;
648 // Calculate the initial position (on Y axis)
649 if (vflip) {
650 starty = height - 2;
651 stepy = -factor;
653 else {
654 starty = 0;
655 stepy = factor;
658 // Calculate the initial position (on X axis)
659 if (hflip) {
660 startx = width - 1;
661 stepx = -factor;
662 offset = width - 2;
664 else {
665 startx = 0;
666 stepx = factor;
667 offset = 1;
671 // Skip the first line
672 bayer += width;
674 // To center vertically the image in the view
675 rgb += ((view->y - nheight) / 2) * view->x * 3;
677 // To center horizontally the image in the view
678 rgb += ((view->x - nwidth) / 2) * 3;
680 // Clean the first line
681 memset(rgb, 0, nwidth * 3);
682 rgb += nwidth * 3;
685 // For each rgb line without the borders (first and last line)
686 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
687 // Go to the start of line
688 b = bayer + y * width + offset;
690 // Offset to center horizontally the image in the view
691 rgb += (view->x - nwidth) * 3;
693 if (y & 0x1) {
694 // Skip the first pixel
695 *rgb++ = 0;
696 *rgb++ = 0;
697 *rgb++ = 0;
699 // GBGBGB : Line process...
700 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
701 if (x & 0x1) {
702 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
703 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
704 *rgb++ = *b;
706 else {
707 *rgb++ = (*(b-width) + *(b+width)) >> 1;
708 *rgb++ = *b;
709 *rgb++ = (*(b-1) + *(b+1)) >> 1;
712 b += stepx;
715 // Skip the last pixel
716 *rgb++ = 0;
717 *rgb++ = 0;
718 *rgb++ = 0;
720 else {
721 // Skip the first pixel
722 *rgb++ = 0;
723 *rgb++ = 0;
724 *rgb++ = 0;
726 // RGRGRG : Line process...
727 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
728 if (x & 0x1) {
729 *rgb++ = (*(b-1) + *(b+1)) >> 1;
730 *rgb++ = *b;
731 *rgb++ = (*(b-width) + *(b+width)) >> 1;
733 else {
734 *rgb++ = *b;
735 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
736 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
739 b += stepx;
742 // Skip the last pixel
743 *rgb++ = 0;
744 *rgb++ = 0;
745 *rgb++ = 0;
749 // Clean the last line
750 memset(rgb, 0, nwidth * 3);
754 /**
755 * @brief This function permits to convert an image from bayer to RGB32
757 * @param bayer Buffer with the bayer data
758 * @param image Size of image
759 * @param view Size of view
760 * @param hflip Horizontal flip
761 * @param vflip Vertical flip
762 * @param factor Factor of redimensioning
764 * @retval rgb Buffer with the RGB data
766 void microdia_b2rgb32(uint8_t *bayer, uint8_t *rgb,
767 struct microdia_coord *image,
768 struct microdia_coord *view,
769 const int hflip, const int vflip,
770 const int factor) {
771 uint8_t *b;
773 int x, y; // Position in bayer image
774 int i, j; // Position in rgb image
776 int width = image->x;
777 int height = image->y;
779 int nwidth = width / factor;
780 int nheight = height / factor;
782 int offset;
783 int startx, stepx;
784 int starty, stepy;
787 // Calculate the initial position (on Y axis)
788 if (vflip) {
789 starty = height - 2;
790 stepy = -factor;
792 else {
793 starty = 0;
794 stepy = factor;
797 // Calculate the initial position (on X axis)
798 if (hflip) {
799 startx = width - 1;
800 stepx = -factor;
801 offset = width - 2;
803 else {
804 startx = 0;
805 stepx = factor;
806 offset = 1;
810 // Skip the first line
811 bayer += width;
813 // To center vertically the image in the view
814 rgb += ((view->y - nheight) / 2) * view->x * 4;
816 // To center horizontally the image in the view
817 rgb += ((view->x - nwidth) / 2) * 4;
819 // Clean the first line
820 memset(rgb, 0, nwidth * 4);
821 rgb += nwidth * 4;
824 // For each rgb line without the borders (first and last line)
825 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
826 // Go to the start of line
827 b = bayer + y * width + offset;
829 // Offset to center horizontally the image in the view
830 rgb += (view->x - nwidth) * 4;
832 if (y & 0x1) {
833 // Skip the first pixel
834 *rgb++ = 0;
835 *rgb++ = 0;
836 *rgb++ = 0;
837 *rgb++ = 0;
839 // GBGBGB : Line process...
840 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
841 if (x & 0x1) {
842 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
843 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
844 *rgb++ = *b;
845 *rgb++ = 0;
847 else {
848 *rgb++ = (*(b-width) + *(b+width)) >> 1;
849 *rgb++ = *b;
850 *rgb++ = (*(b-1) + *(b+1)) >> 1;
851 *rgb++ = 0;
854 b += stepx;
857 // Skip the last pixel
858 *rgb++ = 0;
859 *rgb++ = 0;
860 *rgb++ = 0;
861 *rgb++ = 0;
863 else {
864 // Skip the first pixel
865 *rgb++ = 0;
866 *rgb++ = 0;
867 *rgb++ = 0;
868 *rgb++ = 0;
870 // RGRGRG : Line process...
871 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
872 if (x & 0x1) {
873 *rgb++ = (*(b-1) + *(b+1)) >> 1;
874 *rgb++ = *b;
875 *rgb++ = (*(b-width) + *(b+width)) >> 1;
876 *rgb++ = 0;
878 else {
879 *rgb++ = *b;
880 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
881 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
882 *rgb++ = 0;
885 b += stepx;
888 // Skip the last pixel
889 *rgb++ = 0;
890 *rgb++ = 0;
891 *rgb++ = 0;
892 *rgb++ = 0;
896 // Clean the last line
897 memset(rgb, 0, nwidth * 4);
901 /**
902 * @brief This function permits to convert an image from bayer to BGR24
904 * @param bayer Buffer with the bayer data
905 * @param image Size of image
906 * @param view Size of view
907 * @param hflip Horizontal flip
908 * @param vflip Vertical flip
909 * @param factor Factor of redimensioning
911 * @retval bgr Buffer with the BGR data
913 void microdia_b2bgr24(uint8_t *bayer, uint8_t *bgr,
914 struct microdia_coord *image,
915 struct microdia_coord *view,
916 const int hflip, const int vflip,
917 const int factor) {
918 uint8_t *b;
920 int x, y; // Position in bayer image
921 int i, j; // Position in bgr image
923 int width = image->x;
924 int height = image->y;
926 int nwidth = width / factor;
927 int nheight = height / factor;
929 int offset;
930 int startx, stepx;
931 int starty, stepy;
934 // Calculate the initial position (on Y axis)
935 if (vflip) {
936 starty = height - 2;
937 stepy = -factor;
939 else {
940 starty = 0;
941 stepy = factor;
944 // Calculate the initial position (on X axis)
945 if (hflip) {
946 startx = width - 1;
947 stepx = -factor;
948 offset = width - 2;
950 else {
951 startx = 0;
952 stepx = factor;
953 offset = 1;
957 // Skip the first line
958 bayer += width;
960 // To center vertically the image in the view
961 bgr += ((view->y - nheight) / 2) * view->x * 3;
963 // To center horizontally the image in the view
964 bgr += ((view->x - nwidth) / 2) * 3;
966 // Clean the first line
967 memset(bgr, 0, nwidth * 3);
968 bgr += nwidth * 3;
971 // For each bgr line without the borders (first and last line)
972 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
973 // Go to the start of line
974 b = bayer + y * width + offset;
976 // Offset to center horizontally the image in the view
977 bgr += (view->x - nwidth) * 3;
979 if (y & 0x1) {
980 // Skip the first pixel
981 *bgr++ = 0;
982 *bgr++ = 0;
983 *bgr++ = 0;
985 // GBGBGB : Line process...
986 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
987 if (x & 0x1) {
988 *bgr++ = *b;
989 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
990 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
992 else {
993 *bgr++ = (*(b-1) + *(b+1)) >> 1;
994 *bgr++ = *b;
995 *bgr++ = (*(b-width) + *(b+width)) >> 1;
998 b += stepx;
1001 // Skip the last pixel
1002 *bgr++ = 0;
1003 *bgr++ = 0;
1004 *bgr++ = 0;
1006 else {
1007 // Skip the first pixel
1008 *bgr++ = 0;
1009 *bgr++ = 0;
1010 *bgr++ = 0;
1012 // RGRGRG : Line process...
1013 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1014 if (x & 0x1) {
1015 *bgr++ = (*(b-width) + *(b+width)) >> 1;
1016 *bgr++ = *b;
1017 *bgr++ = (*(b-1) + *(b+1)) >> 1;
1019 else {
1020 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1021 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1022 *bgr++ = *b;
1025 b += stepx;
1028 // Skip the last pixel
1029 *bgr++ = 0;
1030 *bgr++ = 0;
1031 *bgr++ = 0;
1035 // Clean the last line
1036 memset(bgr, 0, nwidth * 3);
1040 /**
1041 * @brief This function permits to convert an image from bayer to BGR32
1043 * @param bayer Buffer with the bayer data
1044 * @param image Size of image
1045 * @param view Size of view
1046 * @param hflip Horizontal flip
1047 * @param vflip Vertical flip
1048 * @param factor Factor of redimensioning
1050 * @retval bgr Buffer with the BGR data
1052 void microdia_b2bgr32(uint8_t *bayer, uint8_t *bgr,
1053 struct microdia_coord *image,
1054 struct microdia_coord *view,
1055 const int hflip, const int vflip,
1056 const int factor) {
1057 uint8_t *b;
1059 int x, y; // Position in bayer image
1060 int i, j; // Position in bgr image
1062 int width = image->x;
1063 int height = image->y;
1065 int nwidth = width / factor;
1066 int nheight = height / factor;
1068 int offset;
1069 int startx, stepx;
1070 int starty, stepy;
1073 // Calculate the initial position (on Y axis)
1074 if (vflip) {
1075 starty = height - 2;
1076 stepy = -factor;
1078 else {
1079 starty = 0;
1080 stepy = factor;
1083 // Calculate the initial position (on X axis)
1084 if (hflip) {
1085 startx = width - 1;
1086 stepx = -factor;
1087 offset = width - 2;
1089 else {
1090 startx = 0;
1091 stepx = factor;
1092 offset = 1;
1096 // Skip the first line
1097 bayer += width;
1099 // To center vertically the image in the view
1100 bgr += ((view->y - nheight) / 2) * view->x * 4;
1102 // To center horizontally the image in the view
1103 bgr += ((view->x - nwidth) / 2) * 4;
1105 // Clean the first line
1106 memset(bgr, 0, nwidth * 4);
1107 bgr += nwidth * 4;
1110 // For each bgr line without the borders (first and last line)
1111 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1112 // Go to the start of line
1113 b = bayer + y * width + offset;
1115 // Offset to center horizontally the image in the view
1116 bgr += (view->x - nwidth) * 4;
1118 if (y & 0x1) {
1119 // Skip the first pixel
1120 *bgr++ = 0;
1121 *bgr++ = 0;
1122 *bgr++ = 0;
1123 *bgr++ = 0;
1125 // GBGBGB : Line process...
1126 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1127 if (x & 0x1) {
1128 *bgr++ = *b;
1129 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1130 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1131 *bgr++ = 0;
1133 else {
1134 *bgr++ = (*(b-1) + *(b+1)) >> 1;
1135 *bgr++ = *b;
1136 *bgr++ = (*(b-width) + *(b+width)) >> 1;
1137 *bgr++ = 0;
1140 b += stepx;
1143 // Skip the last pixel
1144 *bgr++ = 0;
1145 *bgr++ = 0;
1146 *bgr++ = 0;
1147 *bgr++ = 0;
1149 else {
1150 // Skip the first pixel
1151 *bgr++ = 0;
1152 *bgr++ = 0;
1153 *bgr++ = 0;
1154 *bgr++ = 0;
1156 // RGRGRG : Line process...
1157 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1158 if (x & 0x1) {
1159 *bgr++ = (*(b-width) + *(b+width)) >> 1;
1160 *bgr++ = *b;
1161 *bgr++ = (*(b-1) + *(b+1)) >> 1;
1162 *bgr++ = 0;
1164 else {
1165 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1166 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1167 *bgr++ = *b;
1168 *bgr++ = 0;
1171 b += stepx;
1174 // Skip the last pixel
1175 *bgr++ = 0;
1176 *bgr++ = 0;
1177 *bgr++ = 0;
1178 *bgr++ = 0;
1182 // Clean the last line
1183 memset(bgr, 0, nwidth * 4);
1187 /**
1188 * @brief This function permits to convert an image from bayer to YUV (UYVY)
1190 * @param bayer Buffer with the bayer data
1191 * @param image Size of image
1192 * @param view Size of view
1193 * @param hflip Horizontal flip
1194 * @param vflip Vertical flip
1195 * @param factor Factor of redimensioning
1197 * @retval yuv Buffer with the YUV data
1199 void microdia_b2uyvy(uint8_t *bayer, uint8_t *yuv,
1200 struct microdia_coord *image,
1201 struct microdia_coord *view,
1202 const int hflip, const int vflip,
1203 const int factor) {
1204 uint8_t *b;
1206 int x, y; // Position in bayer image
1207 int i, j; // Position in yuv image
1209 int pR, pG, pB;
1210 int pY, pU, pV;
1212 int width = image->x;
1213 int height = image->y;
1215 int nwidth = width / factor;
1216 int nheight = height / factor;
1218 int offset;
1219 int startx, stepx;
1220 int starty, stepy;
1223 // Calculate the initial position (on Y axis)
1224 if (vflip) {
1225 starty = height - 2;
1226 stepy = -factor;
1228 else {
1229 starty = 0;
1230 stepy = factor;
1233 // Calculate the initial position (on X axis)
1234 if (hflip) {
1235 startx = width - 1;
1236 stepx = -factor;
1237 offset = width - 2;
1239 else {
1240 startx = 0;
1241 stepx = factor;
1242 offset = 1;
1245 // Background color...
1246 memset(yuv, 16, width * 2);
1247 for (i=0; i<width*2; i=i+2, *(yuv+i)=128);
1248 for (i=1; i<height; i++)
1249 memcpy(yuv+i*width*2, yuv, width*2);
1251 // Skip the first line
1252 bayer += width;
1254 // To center vertically the image in the view
1255 yuv += ((view->y - nheight) / 2) * view->x * 2;
1257 // To center horizontally the image in the view
1258 yuv += ((view->x - nwidth) / 2) * 2;
1260 // Clean the first line
1261 memset(yuv, 16, nwidth * 2);
1262 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=128);
1263 yuv += nwidth * 2;
1266 // For each yuv line without the borders (first and last line)
1267 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1268 // Go to the start of line
1269 b = bayer + y * width + offset;
1271 // Offset to center horizontally the image in the view
1272 yuv += (view->x - nwidth) * 2;
1274 if (y & 0x1) {
1275 // Skip the first pixel
1276 *yuv++ = 128;
1277 *yuv++ = 16;
1279 // GBGBGB : Line process...
1280 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1281 if (x & 0x1) {
1282 pR = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1283 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1284 pB = *b;
1286 else {
1287 pR = (*(b-width) + *(b+width)) >> 1;
1288 pG = *b;
1289 pB = (*(b-1) + *(b+1)) >> 1;
1292 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1293 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1294 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1296 pY = CLIP(pY, 0,255);
1297 pU = CLIP(pU, -127,127);
1298 pV = CLIP(pV, -127,127);
1300 if (i % 2){
1301 *yuv++ = (112 * pU)/127 + 128; // U
1302 *yuv++ = (219 * pY)/255 + 16; // Y
1304 else {
1305 *yuv++ = (112 * pV)/127 + 128; // V
1306 *yuv++ = (219 * pY)/255 + 16; // Y
1309 b += stepx;
1312 // Skip the last pixel
1313 *yuv++ = 128;
1314 *yuv++ = 16;
1316 else {
1317 // Skip the first pixel
1318 *yuv++ = 128;
1319 *yuv++ = 16;
1321 // RGRGRG : Line process...
1322 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1323 if (x & 0x1) {
1324 pR = (*(b-1) + *(b+1)) >> 1;
1325 pG = *b;
1326 pB = (*(b-width) + *(b+width)) >> 1;
1328 else {
1329 pR = *b;
1330 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1331 pB = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1334 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1335 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1336 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1338 pY = CLIP(pY, 0,255);
1339 pU = CLIP(pU, -127,127);
1340 pV = CLIP(pV, -127,127);
1342 if (i % 2){
1343 *yuv++ = (112 * pU)/127 + 128; // U
1344 *yuv++ = (219 * pY)/255 + 16; // Y
1346 else {
1347 *yuv++ = (112 * pV)/127 + 128; // V
1348 *yuv++ = (219 * pY)/255 + 16; // Y
1351 b += stepx;
1354 // Skip the last pixel
1355 *yuv++ = 128;
1356 *yuv++ = 16;
1360 // Clean the last line
1361 memset(yuv, 16, nwidth * 2);
1362 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=128);
1366 /**
1367 * @brief This function permits to convert an image from bayer to YUV (YUYV)
1369 * @param bayer Buffer with the bayer data
1370 * @param image Size of image
1371 * @param view Size of view
1372 * @param hflip Horizontal flip
1373 * @param vflip Vertical flip
1374 * @param factor Factor of redimensioning
1376 * @retval yuv Buffer with the YUV data
1378 void microdia_b2yuyv(uint8_t *bayer, uint8_t *yuv,
1379 struct microdia_coord *image,
1380 struct microdia_coord *view,
1381 const int hflip, const int vflip,
1382 const int factor) {
1383 uint8_t *b;
1385 int x, y; // Position in bayer image
1386 int i, j; // Position in yuv image
1388 int pR, pG, pB;
1389 int pY, pU, pV;
1391 int width = image->x;
1392 int height = image->y;
1394 int nwidth = width / factor;
1395 int nheight = height / factor;
1397 int offset;
1398 int startx, stepx;
1399 int starty, stepy;
1402 // Calculate the initial position (on Y axis)
1403 if (vflip) {
1404 starty = height - 2;
1405 stepy = -factor;
1407 else {
1408 starty = 0;
1409 stepy = factor;
1412 // Calculate the initial position (on X axis)
1413 if (hflip) {
1414 startx = width - 1;
1415 stepx = -factor;
1416 offset = width - 2;
1418 else {
1419 startx = 0;
1420 stepx = factor;
1421 offset = 1;
1424 // Background color...
1425 memset(yuv, 128, width * 2);
1426 for (i=0; i<width*2; i=i+2, *(yuv+i)=16);
1427 for (i=1; i<height; i++)
1428 memcpy(yuv+i*width*2, yuv, width*2);
1430 // Skip the first line
1431 bayer += width;
1433 // To center vertically the image in the view
1434 yuv += ((view->y - nheight) / 2) * view->x * 2;
1436 // To center horizontally the image in the view
1437 yuv += ((view->x - nwidth) / 2) * 2;
1439 // Clean the first line
1440 memset(yuv, 128, nwidth * 2);
1441 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=16);
1442 yuv += nwidth * 2;
1445 // For each yuv line without the borders (first and last line)
1446 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1447 // Go to the start of line
1448 b = bayer + y * width + offset;
1450 // Offset to center horizontally the image in the view
1451 yuv += (view->x - nwidth) * 2;
1453 if (y & 0x1) {
1454 // Skip the first pixel
1455 *yuv++ = 16;
1456 *yuv++ = 128;
1458 // GBGBGB : Line process...
1459 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1460 if (x & 0x1) {
1461 pR = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1462 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1463 pB = *b;
1465 else {
1466 pR = (*(b-width) + *(b+width)) >> 1;
1467 pG = *b;
1468 pB = (*(b-1) + *(b+1)) >> 1;
1471 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1472 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1473 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1475 pY = CLIP(pY, 0,255);
1476 pU = CLIP(pU, -127,127);
1477 pV = CLIP(pV, -127,127);
1479 if (i % 2){
1480 *yuv++ = (219 * pY)/255 + 16; // Y
1481 *yuv++ = (112 * pU)/127 + 128; // U
1483 else {
1484 *yuv++ = (219 * pY)/255 + 16; // Y
1485 *yuv++ = (112 * pV)/127 + 128; // V
1488 b += stepx;
1491 // Skip the last pixel
1492 *yuv++ = 16;
1493 *yuv++ = 128;
1495 else {
1496 // Skip the first pixel
1497 *yuv++ = 16;
1498 *yuv++ = 128;
1500 // RGRGRG : Line process...
1501 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1502 if (x & 0x1) {
1503 pR = (*(b-1) + *(b+1)) >> 1;
1504 pG = *b;
1505 pB = (*(b-width) + *(b+width)) >> 1;
1507 else {
1508 pR = *b;
1509 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1510 pB = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1513 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1514 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1515 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1517 pY = CLIP(pY, 0,255);
1518 pU = CLIP(pU, -127,127);
1519 pV = CLIP(pV, -127,127);
1521 if (i % 2){
1522 *yuv++ = (219 * pY)/255 + 16; // Y
1523 *yuv++ = (112 * pU)/127 + 128; // U
1525 else {
1526 *yuv++ = (219 * pY)/255 + 16; // Y
1527 *yuv++ = (112 * pV)/127 + 128; // V
1530 b += stepx;
1533 // Skip the last pixel
1534 *yuv++ = 16;
1535 *yuv++ = 128;
1539 // Clean the last line
1540 memset(yuv, 128, nwidth * 2);
1541 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=16);