Detection of camera rotation for 624f implemented
[microdia.git] / microdia-bayer.c
blob472fba3c5eaa6061d78cb43585ecf062f1177657
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 void raw6270_2i420(uint8_t *, uint8_t *, struct microdia_coord *,
53 struct microdia_coord *, const int, const int, const int);
54 void raw6270_2RGB24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
55 struct microdia_coord *view, const int hflip, const int vflip, const int factor);
56 void raw6270_2BGR24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
57 struct microdia_coord *view, const int hflip, 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, const int);
62 void microdia_raw2bgr24(uint8_t *, uint8_t *, struct microdia_coord *,
63 struct microdia_coord *, const int, const int, const int);
64 void microdia_b2rgb24(uint8_t *, uint8_t *,
65 struct microdia_coord *, struct microdia_coord *,
66 const int, const int, const int);
67 void microdia_b2rgb32(uint8_t *, uint8_t *,
68 struct microdia_coord *, struct microdia_coord *,
69 const int, const int, const int);
70 void microdia_b2bgr24(uint8_t *, uint8_t *,
71 struct microdia_coord *, struct microdia_coord *,
72 const int, const int, const int);
73 void microdia_b2bgr32(uint8_t *, uint8_t *,
74 struct microdia_coord *, struct microdia_coord *,
75 const int, const int, const int);
77 void microdia_b2uyvy(uint8_t *, uint8_t *,
78 struct microdia_coord *, struct microdia_coord *,
79 const int, const int, const int);
80 void microdia_b2yuyv(uint8_t *, uint8_t *,
81 struct microdia_coord *, struct microdia_coord *,
82 const int, const int, const int);
85 void microdia_correct_brightness(uint8_t *, const int, const int,
86 const int, int, int);
89 static signed short microdia_yuv_interp[256][8] = {
90 {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},
91 {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},
92 {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},
93 {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},
94 {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},
95 {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},
96 {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},
97 {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},
98 {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},
99 {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},
100 {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},
101 {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},
102 {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},
103 {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},
104 {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},
105 {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},
106 {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},
107 {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},
108 {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},
109 {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},
110 {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},
111 {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},
112 {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},
113 {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},
114 {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},
115 {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},
116 {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},
117 {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},
118 {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},
119 {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},
120 {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},
121 {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},
122 {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},
123 {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},
124 {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},
125 {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},
126 {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},
127 {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},
128 {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},
129 {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},
130 {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},
131 {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},
132 {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},
133 {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},
134 {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},
135 {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},
136 {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},
137 {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},
138 {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},
139 {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},
140 {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},
141 {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},
142 {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},
143 {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},
144 {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},
145 {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},
146 {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},
147 {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},
148 {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},
149 {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},
150 {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},
151 {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},
152 {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},
153 {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}
157 /**
158 * @brief Decompress a frame
160 * This function permits to decompress a frame from the video stream.
162 * @param dev Device structure
164 * @returns 0 if all is OK
166 int microdia_decompress(struct usb_microdia *dev)
168 int size;
169 int factor;
171 void *data;
172 void *image;
173 struct microdia_frame_buf *framebuf;
175 if (dev == NULL)
176 return -EFAULT;
178 framebuf = dev->read_frame;
180 if (framebuf == NULL)
181 return -EFAULT;
183 if (dev->flip_detect) {
184 dev->flip_detect(dev);
186 image = dev->image_data;
187 image += dev->images[dev->fill_image].offset;
189 data = framebuf->data;
190 size = framebuf->filled;
192 switch (dev->resolution) {
193 case MICRODIA_80x60:
194 factor = 8;
195 break;
197 /*case MICRODIA_128x96:
198 factor = 5;
199 break;*/
201 case MICRODIA_160x120:
202 factor = 4;
203 break;
205 /*case MICRODIA_213x160:
206 factor = 3;
207 break;*/
209 case MICRODIA_320x240:
210 factor = 2;
211 break;
213 case MICRODIA_640x480:
214 factor = 1;
215 break;
217 case MICRODIA_800x600:
218 factor = 1;
219 break;
221 case MICRODIA_1024x768:
222 factor = 1;
223 break;
225 case MICRODIA_1280x1024:
226 factor = 1;
227 break;
229 default:
230 return -EFAULT;
234 switch (dev->vsettings.palette) {
235 case MICRODIA_PALETTE_RGB24:
236 if(dev->webcam_model == MICRODIA_6270
237 || dev->webcam_model == MICRODIA_627B)
239 raw6270_2RGB24(data, image, &dev->image, &dev->view,
240 dev->vsettings.hflip, dev->vsettings.vflip, factor);
241 }else
243 microdia_raw2bgr24(data, image, &dev->image, &dev->view,
244 dev->vsettings.hflip, dev->vsettings.vflip, factor);
246 break;
248 case MICRODIA_PALETTE_BGR24:
249 if(dev->webcam_model == MICRODIA_6270
250 || dev->webcam_model == MICRODIA_627B)
252 raw6270_2BGR24(data, image, &dev->image, &dev->view,
253 dev->vsettings.hflip, dev->vsettings.vflip, factor);
254 }else
256 microdia_raw2bgr24(data, image, &dev->image, &dev->view,
257 dev->vsettings.hflip, dev->vsettings.vflip, factor);
259 break;
262 case MICRODIA_PALETTE_RGB32:
264 microdia_b2rgb32(data, image, &dev->image, &dev->view,
265 dev->vsettings.hflip, dev->vsettings.vflip, factor);
266 break;
268 case MICRODIA_PALETTE_BGR32:
269 microdia_b2bgr32(data, image, &dev->image, &dev->view,
270 dev->vsettings.hflip, dev->vsettings.vflip, factor);
271 break;
273 case MICRODIA_PALETTE_UYVY:
274 microdia_b2uyvy(data, image, &dev->image, &dev->view,
275 dev->vsettings.hflip, dev->vsettings.vflip, factor);
276 break;
278 case MICRODIA_PALETTE_YUYV:
279 microdia_b2yuyv(data, image, &dev->image, &dev->view,
280 dev->vsettings.hflip, dev->vsettings.vflip, factor);
281 break;
283 case MICRODIA_PALETTE_I420:
284 if(dev->webcam_model == MICRODIA_6270
285 || dev->webcam_model == MICRODIA_627B)
287 raw6270_2i420(data, image, &dev->image, &dev->view,
288 dev->vsettings.hflip, dev->vsettings.vflip, factor);
289 } else
291 microdia_raw2i420(data, image, &dev->image, &dev->view,
292 dev->vsettings.hflip, dev->vsettings.vflip, factor);
294 break;
295 default:
296 microdia_getraw(data, image, size);
297 break;
300 //microdia_correct_brightness(image, dev->view.x, dev->view.y,
301 // dev->vsettings.brightness, dev->vsettings.palette, dev->vsettings.depth);
303 return 0;
308 * @brief Correct the brightness of an image.
310 * This function permits to correct the brightness of an image.
312 * @param img Buffer to RGB/YUV data
313 * @param width Width of frame
314 * @param height Height of frame
315 * @param brightness Brightness correction
316 * @param palette
317 * @param depth Color depth
319 * @retval rgb Buffer to RGB/YUV data
321 void microdia_correct_brightness(uint8_t *img, const int width, const int height,
322 const int brightness, int palette, int depth)
324 int i;
325 int x;
328 switch (palette) {
329 case MICRODIA_PALETTE_RGB24:
330 case MICRODIA_PALETTE_BGR24:
331 case MICRODIA_PALETTE_RGB32:
332 case MICRODIA_PALETTE_BGR32:
333 depth = (depth == 24) ? 3 : 4;
335 if (brightness >= 32767) {
336 x = (brightness - 32767) / 256;
338 for (i = 0; i < (width * height * depth); i++) {
339 if ((*(img + i) + (unsigned char) x) > 255)
340 *(img + i) = 255;
341 else
342 *(img + i) += (unsigned char) x;
345 else {
346 x = (32767 - brightness) / 256;
348 for (i = 0; i < (width * height * depth); i++) {
349 if ((unsigned char) x > *(img + i))
350 *(img + i) = 0;
351 else
352 *(img + i) -= (unsigned char) x;
356 break;
358 case MICRODIA_PALETTE_UYVY:
359 depth = 2;
361 if (brightness >= 32767) {
362 x = (brightness - 32767) / 256;
364 for (i = 1; i < (width * height * depth); i=i+depth) {
365 if ((*(img + i) + (unsigned char) x) > 255)
366 *(img + i) = 255;
367 else
368 *(img + i) += (unsigned char) x;
371 else {
372 x = (32767 - brightness) / 256;
374 for (i = 1; i < (width * height * depth); i=i+depth) {
375 if ((unsigned char) x > *(img + i))
376 *(img + i) = 0;
377 else
378 *(img + i) -= (unsigned char) x;
382 break;
384 case MICRODIA_PALETTE_YUYV:
385 depth = 2;
387 if (brightness >= 32767) {
388 x = (brightness - 32767) / 256;
390 for (i = 0; i < (width * height * depth); i=i+depth) {
391 if ((*(img + i) + (unsigned char) x) > 255)
392 *(img + i) = 255;
393 else
394 *(img + i) += (unsigned char) x;
397 else {
398 x = (32767 - brightness) / 256;
400 for (i = 0; i < (width * height * depth); i=i+depth) {
401 if ((unsigned char) x > *(img + i))
402 *(img + i) = 0;
403 else
404 *(img + i) -= (unsigned char) x;
408 break;
413 /**
414 * @brief This function permits to get the raw data. (without treatments)
416 * @param bayer Buffer with the bayer data
417 * @param size Length of bayer buffer
419 * @retval raw Buffer with the data from video sensor
421 void microdia_getraw(uint8_t *bayer, uint8_t *raw,
422 int size) {
423 memcpy(raw, bayer, size);
426 /* Table to translate Y offset to UV offset */
427 static int UVTranslate[32] = {0, 1, 2, 3,
428 8, 9, 10, 11,
429 16, 17, 18, 19,
430 24, 25, 26, 27,
431 4, 5, 6, 7,
432 12, 13, 14, 15,
433 20, 21, 22, 23,
434 28, 29, 30, 31};
436 void microdia_raw2bgr24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
437 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
439 int i = 0, x = 0, y = 0;
440 unsigned char *buf = raw;
441 unsigned char *buf3 = rgb;
442 int fwidth, fheight;
444 fwidth = image->x / factor;
445 fheight = image->y / factor;
447 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
448 int tile = 0;
449 for (tile = 0; tile < 4; tile++) {
450 int subX = 0;
451 int subY = 0;
452 for (subY = 0; subY < 4; subY++) {
453 for (subX = 0; subX < 8; subX++) {
454 int subI = i + tile * 32 + 8 * subY + subX;
455 int subU = i + 128 + UVTranslate[tile * 8 + 4 * (subY >> 1) + (subX >> 1)];
456 int subV = subU + 32;
458 int relX = x + (((tile == 0) || (tile == 1)) ? 0 : 8) + subX; //tile 0, 1 to into left comumn
459 int relY = y + (((tile == 0) || (tile == 2)) ? 0 : 4) + subY; //tile 0, 2 go into top row
461 if (hflip) {
462 relX = image->x - relX;
464 if (vflip) {
465 relY = image->y - relY;
468 relX /= factor;
469 relY /= factor;
471 relX += (view->x - fwidth) >> 1;
472 relY += (view->y - fheight) >> 1;
473 if ((relX < view->x) && (relY < view->y)) {
474 unsigned char *ptr;
475 int c, d, e;
476 c = buf[subI] - 16;
477 d = buf[subU] - 128;
478 e = buf[subV] - 128;
480 ptr = buf3 + relY * view->x * 3 + relX * 3;
481 *ptr = CLIP((298 * c + 516 * d + 128) >> 8, 0, 255);
482 ptr++;
483 *ptr = CLIP((298 * c - 100 * d - 208 * e + 128) >> 8, 0, 255);
484 ptr++;
485 *ptr = CLIP((298 * c + 409 * e + 128) >> 8, 0, 255);
491 i += 192;
492 x += 16;
493 if (x >= image->x) {
494 x = 0;
495 y += 8;
500 void microdia_raw2i420(uint8_t *raw, uint8_t *i420, struct microdia_coord *image,
501 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
503 int i = 0, x = 0, y = 0;
504 unsigned char *buf = raw;
505 unsigned char *buf3 = i420;
506 int fwidth, fheight;
508 fwidth = image->x / factor;
509 fheight = image->y / factor;
511 //printk(KERN_INFO "image: %d %d, view: %d %d factor: %d\n", image->x, image->y, view->x, view->y, factor);
513 while (i < (image->x * image->y + (image->x * image->y) / 2)) {
514 int tile = 0;
515 for (tile = 0; tile < 4; tile++) {
516 int subX = 0;
517 int subY = 0;
518 for (subY = 0; subY < 4; subY++) {
519 for (subX = 0; subX < 8; subX++) {
520 int subI = i + tile * 32 + 8 * subY + subX;
521 int subU = i + 128 + UVTranslate[tile * 8 + 4 * (subY >> 1) + (subX >> 1)];
522 int subV = subU + 32;
524 int relX = x + (((tile == 0) || (tile == 1)) ? 0 : 8) + subX; //tile 0, 1 to into left comumn
525 int relY = y + (((tile == 0) || (tile == 2)) ? 0 : 4) + subY; //tile 0, 2 go into top row
527 if (hflip) {
528 relX = image->x - relX;
530 if (vflip) {
531 relY = image->y - relY;
534 relX /= factor;
535 relY /= factor;
537 relX += (view->x - fwidth) >> 1;
538 relY += (view->y - fheight) >> 1;
539 if ((relX < view->x) && (relY < view->y)) {
540 unsigned char *ptr;
542 ptr = buf3 + relY * view->x + relX;
543 *ptr = buf[subI];
544 ptr = (buf3 + (view->x * view->y) + (relY / 2) * (view->x / 2) + (relX / 2));
545 *ptr = buf[subU];
546 ptr = (buf3 + (view->x * view->y) + (view->x * view->y / 4) + (relY / 2) *
547 (view->x / 2)+ (relX / 2));
548 *ptr = buf[subV];
554 i += 192;
555 x += 16;
556 if (x >= image->x) {
557 x = 0;
558 y += 8;
564 /**
566 * @brief This function permits to convert an image from 6270 raw format to i420
567 * @param raw Buffer with the bayer data
568 * @param image Size of image
569 * @param view Size of view
570 * @param hflip Horizontal flip - not implemented
571 * @param vflip Vertical flip - not implemented
572 * @param factor Factor of redimensioning - not used factor is recalculate to do any non standard transformations
574 * @retval i420 Buffer with the i420 data
575 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
576 y - repeated 640 times for 640x480
577 First 1280 bytes is maybe dumy ***FIX ME***
580 void raw6270_2i420(uint8_t *raw, uint8_t *i420, struct microdia_coord *image,
581 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
583 int i, j, YIndex = 0, UVIndex = 0;
584 unsigned char *y, *u, *v;
585 uint8_t *buf;
586 int hshift, vshift;
587 //For fast calculations
588 int x_div_2,y_div_2;
589 //Skip first 1280 bytes strange dummy bytes
590 raw+=1280;
592 x_div_2=image->x / 2; //for fast calculation if x=640 x_div_2=320
593 y_div_2=image->y / 2; //for fast calculation if y=480 y_div_4=240
594 buf=raw;
595 y = i420;
596 u = i420 + view->x * view->y;
597 v = i420 + view->x * view->y + (view->x >> 1) * (view->y >> 1);
599 hshift = view->x - (image->x / factor);
600 hshift >>= 1;
601 vshift = view->y - (image->y / factor);
602 vshift >>= 1;
604 YIndex = vshift * view->x + hshift;
605 UVIndex = (vshift >> 1) * (view->x >> 1) + (hshift >> 1);
606 //we skipped 1280 bytes, it's almost two lines
607 for (i = 0; i < y_div_2 - 1; i++) {
608 for (j = 0; j < x_div_2; j ++) {
609 u[UVIndex] = *buf;
610 buf++;
611 v[UVIndex] = *buf;
612 buf++;
613 y[YIndex] = *buf;
614 buf++;
615 YIndex += ((j * 2) % factor) == 0 ? 1 : 0;
616 y[YIndex] = *buf;
617 buf++;
618 YIndex += ((j * 2 + 1) % factor) == 0 ? 1 : 0;
619 UVIndex += (j % factor) == 0 ? 1 : 0;
621 YIndex -= hshift;
622 YIndex -= (image->x / factor);
623 if ((i * 2) % factor == 0) YIndex += view->x + hshift;
624 else YIndex += hshift;
626 for (j = 0; j < image->x; j++) {
627 y[YIndex] = *buf;
628 buf++;
629 YIndex += (j % factor) == 0 ? 1 : 0;
631 YIndex -= hshift;
632 YIndex -= (image->x / factor);
633 if ((i * 2 + 1) % factor == 0) YIndex += view->x + hshift;
634 else YIndex += hshift;
636 UVIndex -= (hshift >> 1);
637 UVIndex -= x_div_2 / factor;
638 if (i % factor == 0) UVIndex += (view->x >> 1) + (hshift >> 1);
639 else UVIndex += (hshift >> 1);
643 /**
645 * @brief This function permits to convert an image from 6270 raw format to BGR24
646 * @param raw Buffer with the bayer data
647 * @param image Size of image
648 * @param view Size of view
649 * @param hflip Horizontal flip - not implemented yet
650 * @param vflip Vertical flip - not implemented yet
651 * @param factor Factor of redimensioning - not used factor is recalculate to do any non standard transformations
653 * @retval rgb Buffer with the rgb data
654 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
655 y - repeated 640 times for 640x480
656 First 1280 bytes is maybe dumy ***FIX ME***
659 void raw6270_2BGR24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
660 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
662 int i, j, incX;
663 //Maybe is not necesery to use long variables but I not sure in this moment
664 long y11,y12,y21,y22, u, v,y,C,D,E;
665 long ScaleIncX,ScaleIncY;
666 long pointerIncX,pointerIncY;
667 uint8_t *bufUVYY;
668 uint8_t *bufY;
669 uint8_t *out_row1;
670 uint8_t *out_row2;
672 //For fast calculations
673 int x_div_2,y_div_2;
674 //Skip first 1280 bytes strange dummy bytes
675 raw+=1280;
677 x_div_2=image->x / 2; //for fast calculation if x=640 x_div_2=320
678 y_div_2=image->y / 2; //for fast calculation if y=480 y_div_4=240
679 incX=3*view->x; //Incrementation koeficient for next row
680 bufUVYY=raw;
681 bufY=raw+2*image->x;
683 //Because I can't use float ratio is multiply by 1000 then 1000 is equal of increment image (X or Y) with 1
684 ScaleIncX=(1000*view->x)/image->x;
685 ScaleIncY=(1000*view->y)/image->y;
688 out_row1=rgb;
689 out_row2=out_row1+incX;
690 //we skipped 1280 bytes, it's almost two lines
691 pointerIncY=1000;
692 for (i = 0; i < y_div_2-1; i++) {
693 pointerIncX=1000;
694 for (j = 0; j < x_div_2; j ++) {
696 pointerIncX+=ScaleIncX;
698 u=(unsigned char)(*bufUVYY);
699 bufUVYY++;
700 v=(unsigned char)(*bufUVYY);
701 bufUVYY++;
702 y11=(unsigned char)(*bufUVYY);
703 bufUVYY++;
704 y12=(unsigned char)(*bufUVYY);
705 bufUVYY++;
706 y21=(unsigned char)(*bufY);
707 bufY++;
708 y22=(unsigned char)(*bufY);
709 bufY++;
711 if((pointerIncX>999)&&(pointerIncY>499)){
712 pointerIncX-=1001;
713 y=y11;
714 C = y - 16;
715 D = u - 128;
716 E = v - 128;
718 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
719 out_row1++;
720 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
721 out_row1++;
722 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
723 out_row1++;
725 y=y12;
727 C = y - 16;
728 D = u - 128;
729 E = v - 128;
732 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
733 out_row1++;
734 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
735 out_row1++;
736 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
737 out_row1++;
740 //Second row of stream is displayed only if image is greath than half
741 if(ScaleIncY>501)
743 y=y21;
745 C = y - 16;
746 D = u - 128;
747 E = v - 128;
749 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
750 out_row2++;
751 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
752 out_row2++;
753 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
754 out_row2++;
756 y=y22;
758 C = y - 16;
759 D = u - 128;
760 E = v - 128;
762 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
763 out_row2++;
764 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
765 out_row2++;
766 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
767 out_row2++;
771 //this comparation can be optimized and moved in if((pointerIncX>999)&&(pointerIncY>499))
772 if(pointerIncY>499)
773 pointerIncY-=500;
774 //Use 2 rows only if vertical ratio > 0.5 (increment is ratio*1000)
775 if(ScaleIncY>501)
777 out_row1=out_row1+incX;
778 out_row2=out_row2+incX;
782 pointerIncY+= ScaleIncY;
783 bufUVYY=bufUVYY+image->x;
784 bufY=bufY+2*image->x;
790 /**
792 * @brief This function permits to convert an image from 6270 raw format to RGB24
793 * @brief The same function as convert to BGR24 but only B and R is change order
794 * @param raw Buffer with the bayer data
795 * @param image Size of image
796 * @param view Size of view
797 * @param hflip Horizontal flip
798 * @param vflip Vertical flip
799 * @param factor Factor of redimensioning
801 * @retval rgb Buffer with the rgb data
802 Format of stream is uvyy,uvyy - repeated 320 times for 640x480
803 y - repeated 640 times for 640x480
804 First 1280 bytes is maybe dumy ***FIX ME***
807 void raw6270_2RGB24(uint8_t *raw, uint8_t *rgb, struct microdia_coord *image,
808 struct microdia_coord *view, const int hflip, const int vflip, const int factor)
810 int i, j, incX;
811 //Maybe is not necesery to use long variables but I not sure in this moment
812 long y11,y12,y21,y22, u, v,y,C,D,E;
813 long ScaleIncX,ScaleIncY;
814 long pointerIncX,pointerIncY;
815 uint8_t *bufUVYY;
816 uint8_t *bufY;
817 uint8_t *out_row1;
818 uint8_t *out_row2;
820 //For fast calculations
821 int x_div_2,y_div_2;
822 //Skip first 1280 bytes strange dummy bytes
823 raw+=1280;
825 x_div_2=image->x / 2; //for fast calculation if x=640 x_div_2=320
826 y_div_2=image->y / 2; //for fast calculation if y=480 y_div_4=240
827 incX=3*view->x;
828 bufUVYY=raw;
829 bufY=raw+2*image->x;
831 //Because I can't use float ratio is multiply by 1000 then 1000 is equal of increment image (X or Y) with 1
832 ScaleIncX=(1000*view->x)/image->x;
833 ScaleIncY=(1000*view->y)/image->y;
836 out_row1=rgb;
837 out_row2=out_row1+incX;
838 //we skipped 1280 bytes, it's almost two lines
839 pointerIncY=1000;
840 for (i = 0; i < y_div_2-1; i++) {
841 pointerIncX=1000;
842 for (j = 0; j < x_div_2; j ++) {
844 pointerIncX+=ScaleIncX;
846 u=(unsigned char)(*bufUVYY);
847 bufUVYY++;
848 v=(unsigned char)(*bufUVYY);
849 bufUVYY++;
850 y11=(unsigned char)(*bufUVYY);
851 bufUVYY++;
852 y12=(unsigned char)(*bufUVYY);
853 bufUVYY++;
854 y21=(unsigned char)(*bufY);
855 bufY++;
856 y22=(unsigned char)(*bufY);
857 bufY++;
859 if((pointerIncX>999)&&(pointerIncY>499)){
860 pointerIncX-=1001;
861 y=y11;
862 C = y - 16;
863 D = u - 128;
864 E = v - 128;
866 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
867 out_row1++;
868 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
869 out_row1++;
870 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
871 out_row1++;
873 y=y12;
875 C = y - 16;
876 D = u - 128;
877 E = v - 128;
880 *out_row1=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
881 out_row1++;
882 *out_row1=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
883 out_row1++;
884 *out_row1=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
885 out_row1++;
888 //Second row of stream is displayed only if image is greath than half
889 if(ScaleIncY>501)
891 y=y21;
893 C = y - 16;
894 D = u - 128;
895 E = v - 128;
897 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
898 out_row2++;
899 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
900 out_row2++;
901 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
902 out_row2++;
904 y=y22;
906 C = y - 16;
907 D = u - 128;
908 E = v - 128;
910 *out_row2=CLIP((298 * C + 409 * E + 128) >> 8, 0, 255);
911 out_row2++;
912 *out_row2=CLIP((298 * C - 100 * D - 208 * E + 128) >> 8, 0, 255);
913 out_row2++;
914 *out_row2=CLIP((298 * C + 516 * D + 128) >> 8, 0, 255);
915 out_row2++;
919 //this comparation can be optimized and moved in if((pointerIncX>999)&&(pointerIncY>499))
920 if(pointerIncY>499)
921 pointerIncY-=500;
922 //Use 2 rows only if vertical ratio > 0.5 (increment is ratio*1000)
923 if(ScaleIncY>501)
925 out_row1=out_row1+incX;
926 out_row2=out_row2+incX;
930 pointerIncY+= ScaleIncY;
931 bufUVYY=bufUVYY+image->x;
932 bufY=bufY+2*image->x;
938 /**
939 * @brief This function permits to convert an image from bayer to RGB24
941 * @param bayer Buffer with the bayer data
942 * @param image Size of image
943 * @param view Size of view
944 * @param hflip Horizontal flip
945 * @param vflip Vertical flip
946 * @param factor Factor of redimensioning
948 * @retval rgb Buffer with the RGB data
950 void microdia_b2rgb24(uint8_t *bayer, uint8_t *rgb,
951 struct microdia_coord *image,
952 struct microdia_coord *view,
953 const int hflip, const int vflip,
954 const int factor) {
955 uint8_t *b;
957 int x, y; // Position in bayer image
958 int i, j; // Position in rgb image
960 int width = image->x;
961 int height = image->y;
963 int nwidth = width / factor;
964 int nheight = height / factor;
966 int offset;
967 int startx, stepx;
968 int starty, stepy;
971 // Calculate the initial position (on Y axis)
972 if (vflip) {
973 starty = height - 2;
974 stepy = -factor;
976 else {
977 starty = 0;
978 stepy = factor;
981 // Calculate the initial position (on X axis)
982 if (hflip) {
983 startx = width - 1;
984 stepx = -factor;
985 offset = width - 2;
987 else {
988 startx = 0;
989 stepx = factor;
990 offset = 1;
994 // Skip the first line
995 bayer += width;
997 // To center vertically the image in the view
998 rgb += ((view->y - nheight) / 2) * view->x * 3;
1000 // To center horizontally the image in the view
1001 rgb += ((view->x - nwidth) / 2) * 3;
1003 // Clean the first line
1004 memset(rgb, 0, nwidth * 3);
1005 rgb += nwidth * 3;
1008 // For each rgb line without the borders (first and last line)
1009 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1010 // Go to the start of line
1011 b = bayer + y * width + offset;
1013 // Offset to center horizontally the image in the view
1014 rgb += (view->x - nwidth) * 3;
1016 if (y & 0x1) {
1017 // Skip the first pixel
1018 *rgb++ = 0;
1019 *rgb++ = 0;
1020 *rgb++ = 0;
1022 // GBGBGB : Line process...
1023 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1024 if (x & 0x1) {
1025 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1026 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1027 *rgb++ = *b;
1029 else {
1030 *rgb++ = (*(b-width) + *(b+width)) >> 1;
1031 *rgb++ = *b;
1032 *rgb++ = (*(b-1) + *(b+1)) >> 1;
1035 b += stepx;
1038 // Skip the last pixel
1039 *rgb++ = 0;
1040 *rgb++ = 0;
1041 *rgb++ = 0;
1043 else {
1044 // Skip the first pixel
1045 *rgb++ = 0;
1046 *rgb++ = 0;
1047 *rgb++ = 0;
1049 // RGRGRG : Line process...
1050 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1051 if (x & 0x1) {
1052 *rgb++ = (*(b-1) + *(b+1)) >> 1;
1053 *rgb++ = *b;
1054 *rgb++ = (*(b-width) + *(b+width)) >> 1;
1056 else {
1057 *rgb++ = *b;
1058 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1059 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1062 b += stepx;
1065 // Skip the last pixel
1066 *rgb++ = 0;
1067 *rgb++ = 0;
1068 *rgb++ = 0;
1072 // Clean the last line
1073 memset(rgb, 0, nwidth * 3);
1077 /**
1078 * @brief This function permits to convert an image from bayer to RGB32
1080 * @param bayer Buffer with the bayer data
1081 * @param image Size of image
1082 * @param view Size of view
1083 * @param hflip Horizontal flip
1084 * @param vflip Vertical flip
1085 * @param factor Factor of redimensioning
1087 * @retval rgb Buffer with the RGB data
1089 void microdia_b2rgb32(uint8_t *bayer, uint8_t *rgb,
1090 struct microdia_coord *image,
1091 struct microdia_coord *view,
1092 const int hflip, const int vflip,
1093 const int factor) {
1094 uint8_t *b;
1096 int x, y; // Position in bayer image
1097 int i, j; // Position in rgb image
1099 int width = image->x;
1100 int height = image->y;
1102 int nwidth = width / factor;
1103 int nheight = height / factor;
1105 int offset;
1106 int startx, stepx;
1107 int starty, stepy;
1110 // Calculate the initial position (on Y axis)
1111 if (vflip) {
1112 starty = height - 2;
1113 stepy = -factor;
1115 else {
1116 starty = 0;
1117 stepy = factor;
1120 // Calculate the initial position (on X axis)
1121 if (hflip) {
1122 startx = width - 1;
1123 stepx = -factor;
1124 offset = width - 2;
1126 else {
1127 startx = 0;
1128 stepx = factor;
1129 offset = 1;
1133 // Skip the first line
1134 bayer += width;
1136 // To center vertically the image in the view
1137 rgb += ((view->y - nheight) / 2) * view->x * 4;
1139 // To center horizontally the image in the view
1140 rgb += ((view->x - nwidth) / 2) * 4;
1142 // Clean the first line
1143 memset(rgb, 0, nwidth * 4);
1144 rgb += nwidth * 4;
1147 // For each rgb line without the borders (first and last line)
1148 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1149 // Go to the start of line
1150 b = bayer + y * width + offset;
1152 // Offset to center horizontally the image in the view
1153 rgb += (view->x - nwidth) * 4;
1155 if (y & 0x1) {
1156 // Skip the first pixel
1157 *rgb++ = 0;
1158 *rgb++ = 0;
1159 *rgb++ = 0;
1160 *rgb++ = 0;
1162 // GBGBGB : Line process...
1163 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1164 if (x & 0x1) {
1165 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1166 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1167 *rgb++ = *b;
1168 *rgb++ = 0;
1170 else {
1171 *rgb++ = (*(b-width) + *(b+width)) >> 1;
1172 *rgb++ = *b;
1173 *rgb++ = (*(b-1) + *(b+1)) >> 1;
1174 *rgb++ = 0;
1177 b += stepx;
1180 // Skip the last pixel
1181 *rgb++ = 0;
1182 *rgb++ = 0;
1183 *rgb++ = 0;
1184 *rgb++ = 0;
1186 else {
1187 // Skip the first pixel
1188 *rgb++ = 0;
1189 *rgb++ = 0;
1190 *rgb++ = 0;
1191 *rgb++ = 0;
1193 // RGRGRG : Line process...
1194 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1195 if (x & 0x1) {
1196 *rgb++ = (*(b-1) + *(b+1)) >> 1;
1197 *rgb++ = *b;
1198 *rgb++ = (*(b-width) + *(b+width)) >> 1;
1199 *rgb++ = 0;
1201 else {
1202 *rgb++ = *b;
1203 *rgb++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1204 *rgb++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1205 *rgb++ = 0;
1208 b += stepx;
1211 // Skip the last pixel
1212 *rgb++ = 0;
1213 *rgb++ = 0;
1214 *rgb++ = 0;
1215 *rgb++ = 0;
1219 // Clean the last line
1220 memset(rgb, 0, nwidth * 4);
1224 /**
1225 * @brief This function permits to convert an image from bayer to BGR24
1227 * @param bayer Buffer with the bayer data
1228 * @param image Size of image
1229 * @param view Size of view
1230 * @param hflip Horizontal flip
1231 * @param vflip Vertical flip
1232 * @param factor Factor of redimensioning
1234 * @retval bgr Buffer with the BGR data
1236 void microdia_b2bgr24(uint8_t *bayer, uint8_t *bgr,
1237 struct microdia_coord *image,
1238 struct microdia_coord *view,
1239 const int hflip, const int vflip,
1240 const int factor) {
1241 uint8_t *b;
1243 int x, y; // Position in bayer image
1244 int i, j; // Position in bgr image
1246 int width = image->x;
1247 int height = image->y;
1249 int nwidth = width / factor;
1250 int nheight = height / factor;
1252 int offset;
1253 int startx, stepx;
1254 int starty, stepy;
1257 // Calculate the initial position (on Y axis)
1258 if (vflip) {
1259 starty = height - 2;
1260 stepy = -factor;
1262 else {
1263 starty = 0;
1264 stepy = factor;
1267 // Calculate the initial position (on X axis)
1268 if (hflip) {
1269 startx = width - 1;
1270 stepx = -factor;
1271 offset = width - 2;
1273 else {
1274 startx = 0;
1275 stepx = factor;
1276 offset = 1;
1280 // Skip the first line
1281 bayer += width;
1283 // To center vertically the image in the view
1284 bgr += ((view->y - nheight) / 2) * view->x * 3;
1286 // To center horizontally the image in the view
1287 bgr += ((view->x - nwidth) / 2) * 3;
1289 // Clean the first line
1290 memset(bgr, 0, nwidth * 3);
1291 bgr += nwidth * 3;
1294 // For each bgr line without the borders (first and last line)
1295 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1296 // Go to the start of line
1297 b = bayer + y * width + offset;
1299 // Offset to center horizontally the image in the view
1300 bgr += (view->x - nwidth) * 3;
1302 if (y & 0x1) {
1303 // Skip the first pixel
1304 *bgr++ = 0;
1305 *bgr++ = 0;
1306 *bgr++ = 0;
1308 // GBGBGB : Line process...
1309 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1310 if (x & 0x1) {
1311 *bgr++ = *b;
1312 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1313 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1315 else {
1316 *bgr++ = (*(b-1) + *(b+1)) >> 1;
1317 *bgr++ = *b;
1318 *bgr++ = (*(b-width) + *(b+width)) >> 1;
1321 b += stepx;
1324 // Skip the last pixel
1325 *bgr++ = 0;
1326 *bgr++ = 0;
1327 *bgr++ = 0;
1329 else {
1330 // Skip the first pixel
1331 *bgr++ = 0;
1332 *bgr++ = 0;
1333 *bgr++ = 0;
1335 // RGRGRG : Line process...
1336 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1337 if (x & 0x1) {
1338 *bgr++ = (*(b-width) + *(b+width)) >> 1;
1339 *bgr++ = *b;
1340 *bgr++ = (*(b-1) + *(b+1)) >> 1;
1342 else {
1343 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1344 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1345 *bgr++ = *b;
1348 b += stepx;
1351 // Skip the last pixel
1352 *bgr++ = 0;
1353 *bgr++ = 0;
1354 *bgr++ = 0;
1358 // Clean the last line
1359 memset(bgr, 0, nwidth * 3);
1363 /**
1364 * @brief This function permits to convert an image from bayer to BGR32
1366 * @param bayer Buffer with the bayer data
1367 * @param image Size of image
1368 * @param view Size of view
1369 * @param hflip Horizontal flip
1370 * @param vflip Vertical flip
1371 * @param factor Factor of redimensioning
1373 * @retval bgr Buffer with the BGR data
1375 void microdia_b2bgr32(uint8_t *bayer, uint8_t *bgr,
1376 struct microdia_coord *image,
1377 struct microdia_coord *view,
1378 const int hflip, const int vflip,
1379 const int factor) {
1380 uint8_t *b;
1382 int x, y; // Position in bayer image
1383 int i, j; // Position in bgr image
1385 int width = image->x;
1386 int height = image->y;
1388 int nwidth = width / factor;
1389 int nheight = height / factor;
1391 int offset;
1392 int startx, stepx;
1393 int starty, stepy;
1396 // Calculate the initial position (on Y axis)
1397 if (vflip) {
1398 starty = height - 2;
1399 stepy = -factor;
1401 else {
1402 starty = 0;
1403 stepy = factor;
1406 // Calculate the initial position (on X axis)
1407 if (hflip) {
1408 startx = width - 1;
1409 stepx = -factor;
1410 offset = width - 2;
1412 else {
1413 startx = 0;
1414 stepx = factor;
1415 offset = 1;
1419 // Skip the first line
1420 bayer += width;
1422 // To center vertically the image in the view
1423 bgr += ((view->y - nheight) / 2) * view->x * 4;
1425 // To center horizontally the image in the view
1426 bgr += ((view->x - nwidth) / 2) * 4;
1428 // Clean the first line
1429 memset(bgr, 0, nwidth * 4);
1430 bgr += nwidth * 4;
1433 // For each bgr line without the borders (first and last line)
1434 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1435 // Go to the start of line
1436 b = bayer + y * width + offset;
1438 // Offset to center horizontally the image in the view
1439 bgr += (view->x - nwidth) * 4;
1441 if (y & 0x1) {
1442 // Skip the first pixel
1443 *bgr++ = 0;
1444 *bgr++ = 0;
1445 *bgr++ = 0;
1446 *bgr++ = 0;
1448 // GBGBGB : Line process...
1449 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1450 if (x & 0x1) {
1451 *bgr++ = *b;
1452 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1453 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1454 *bgr++ = 0;
1456 else {
1457 *bgr++ = (*(b-1) + *(b+1)) >> 1;
1458 *bgr++ = *b;
1459 *bgr++ = (*(b-width) + *(b+width)) >> 1;
1460 *bgr++ = 0;
1463 b += stepx;
1466 // Skip the last pixel
1467 *bgr++ = 0;
1468 *bgr++ = 0;
1469 *bgr++ = 0;
1470 *bgr++ = 0;
1472 else {
1473 // Skip the first pixel
1474 *bgr++ = 0;
1475 *bgr++ = 0;
1476 *bgr++ = 0;
1477 *bgr++ = 0;
1479 // RGRGRG : Line process...
1480 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1481 if (x & 0x1) {
1482 *bgr++ = (*(b-width) + *(b+width)) >> 1;
1483 *bgr++ = *b;
1484 *bgr++ = (*(b-1) + *(b+1)) >> 1;
1485 *bgr++ = 0;
1487 else {
1488 *bgr++ = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1489 *bgr++ = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1490 *bgr++ = *b;
1491 *bgr++ = 0;
1494 b += stepx;
1497 // Skip the last pixel
1498 *bgr++ = 0;
1499 *bgr++ = 0;
1500 *bgr++ = 0;
1501 *bgr++ = 0;
1505 // Clean the last line
1506 memset(bgr, 0, nwidth * 4);
1510 /**
1511 * @brief This function permits to convert an image from bayer to YUV (UYVY)
1513 * @param bayer Buffer with the bayer data
1514 * @param image Size of image
1515 * @param view Size of view
1516 * @param hflip Horizontal flip
1517 * @param vflip Vertical flip
1518 * @param factor Factor of redimensioning
1520 * @retval yuv Buffer with the YUV data
1522 void microdia_b2uyvy(uint8_t *bayer, uint8_t *yuv,
1523 struct microdia_coord *image,
1524 struct microdia_coord *view,
1525 const int hflip, const int vflip,
1526 const int factor) {
1527 uint8_t *b;
1529 int x, y; // Position in bayer image
1530 int i, j; // Position in yuv image
1532 int pR, pG, pB;
1533 int pY, pU, pV;
1535 int width = image->x;
1536 int height = image->y;
1538 int nwidth = width / factor;
1539 int nheight = height / factor;
1541 int offset;
1542 int startx, stepx;
1543 int starty, stepy;
1546 // Calculate the initial position (on Y axis)
1547 if (vflip) {
1548 starty = height - 2;
1549 stepy = -factor;
1551 else {
1552 starty = 0;
1553 stepy = factor;
1556 // Calculate the initial position (on X axis)
1557 if (hflip) {
1558 startx = width - 1;
1559 stepx = -factor;
1560 offset = width - 2;
1562 else {
1563 startx = 0;
1564 stepx = factor;
1565 offset = 1;
1568 // Background color...
1569 memset(yuv, 16, width * 2);
1570 for (i=0; i<width*2; i=i+2, *(yuv+i)=128);
1571 for (i=1; i<height; i++)
1572 memcpy(yuv+i*width*2, yuv, width*2);
1574 // Skip the first line
1575 bayer += width;
1577 // To center vertically the image in the view
1578 yuv += ((view->y - nheight) / 2) * view->x * 2;
1580 // To center horizontally the image in the view
1581 yuv += ((view->x - nwidth) / 2) * 2;
1583 // Clean the first line
1584 memset(yuv, 16, nwidth * 2);
1585 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=128);
1586 yuv += nwidth * 2;
1589 // For each yuv line without the borders (first and last line)
1590 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1591 // Go to the start of line
1592 b = bayer + y * width + offset;
1594 // Offset to center horizontally the image in the view
1595 yuv += (view->x - nwidth) * 2;
1597 if (y & 0x1) {
1598 // Skip the first pixel
1599 *yuv++ = 128;
1600 *yuv++ = 16;
1602 // GBGBGB : Line process...
1603 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1604 if (x & 0x1) {
1605 pR = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1606 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1607 pB = *b;
1609 else {
1610 pR = (*(b-width) + *(b+width)) >> 1;
1611 pG = *b;
1612 pB = (*(b-1) + *(b+1)) >> 1;
1615 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1616 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1617 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1619 pY = CLIP(pY, 0,255);
1620 pU = CLIP(pU, -127,127);
1621 pV = CLIP(pV, -127,127);
1623 if (i % 2){
1624 *yuv++ = (112 * pU)/127 + 128; // U
1625 *yuv++ = (219 * pY)/255 + 16; // Y
1627 else {
1628 *yuv++ = (112 * pV)/127 + 128; // V
1629 *yuv++ = (219 * pY)/255 + 16; // Y
1632 b += stepx;
1635 // Skip the last pixel
1636 *yuv++ = 128;
1637 *yuv++ = 16;
1639 else {
1640 // Skip the first pixel
1641 *yuv++ = 128;
1642 *yuv++ = 16;
1644 // RGRGRG : Line process...
1645 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1646 if (x & 0x1) {
1647 pR = (*(b-1) + *(b+1)) >> 1;
1648 pG = *b;
1649 pB = (*(b-width) + *(b+width)) >> 1;
1651 else {
1652 pR = *b;
1653 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1654 pB = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1657 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1658 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1659 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1661 pY = CLIP(pY, 0,255);
1662 pU = CLIP(pU, -127,127);
1663 pV = CLIP(pV, -127,127);
1665 if (i % 2){
1666 *yuv++ = (112 * pU)/127 + 128; // U
1667 *yuv++ = (219 * pY)/255 + 16; // Y
1669 else {
1670 *yuv++ = (112 * pV)/127 + 128; // V
1671 *yuv++ = (219 * pY)/255 + 16; // Y
1674 b += stepx;
1677 // Skip the last pixel
1678 *yuv++ = 128;
1679 *yuv++ = 16;
1683 // Clean the last line
1684 memset(yuv, 16, nwidth * 2);
1685 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=128);
1689 /**
1690 * @brief This function permits to convert an image from bayer to YUV (YUYV)
1692 * @param bayer Buffer with the bayer data
1693 * @param image Size of image
1694 * @param view Size of view
1695 * @param hflip Horizontal flip
1696 * @param vflip Vertical flip
1697 * @param factor Factor of redimensioning
1699 * @retval yuv Buffer with the YUV data
1701 void microdia_b2yuyv(uint8_t *bayer, uint8_t *yuv,
1702 struct microdia_coord *image,
1703 struct microdia_coord *view,
1704 const int hflip, const int vflip,
1705 const int factor) {
1706 uint8_t *b;
1708 int x, y; // Position in bayer image
1709 int i, j; // Position in yuv image
1711 int pR, pG, pB;
1712 int pY, pU, pV;
1714 int width = image->x;
1715 int height = image->y;
1717 int nwidth = width / factor;
1718 int nheight = height / factor;
1720 int offset;
1721 int startx, stepx;
1722 int starty, stepy;
1725 // Calculate the initial position (on Y axis)
1726 if (vflip) {
1727 starty = height - 2;
1728 stepy = -factor;
1730 else {
1731 starty = 0;
1732 stepy = factor;
1735 // Calculate the initial position (on X axis)
1736 if (hflip) {
1737 startx = width - 1;
1738 stepx = -factor;
1739 offset = width - 2;
1741 else {
1742 startx = 0;
1743 stepx = factor;
1744 offset = 1;
1747 // Background color...
1748 memset(yuv, 128, width * 2);
1749 for (i=0; i<width*2; i=i+2, *(yuv+i)=16);
1750 for (i=1; i<height; i++)
1751 memcpy(yuv+i*width*2, yuv, width*2);
1753 // Skip the first line
1754 bayer += width;
1756 // To center vertically the image in the view
1757 yuv += ((view->y - nheight) / 2) * view->x * 2;
1759 // To center horizontally the image in the view
1760 yuv += ((view->x - nwidth) / 2) * 2;
1762 // Clean the first line
1763 memset(yuv, 128, nwidth * 2);
1764 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=16);
1765 yuv += nwidth * 2;
1768 // For each yuv line without the borders (first and last line)
1769 for (j=0, y=starty; j<nheight-2; j++, y=y+stepy) {
1770 // Go to the start of line
1771 b = bayer + y * width + offset;
1773 // Offset to center horizontally the image in the view
1774 yuv += (view->x - nwidth) * 2;
1776 if (y & 0x1) {
1777 // Skip the first pixel
1778 *yuv++ = 16;
1779 *yuv++ = 128;
1781 // GBGBGB : Line process...
1782 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1783 if (x & 0x1) {
1784 pR = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1785 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1786 pB = *b;
1788 else {
1789 pR = (*(b-width) + *(b+width)) >> 1;
1790 pG = *b;
1791 pB = (*(b-1) + *(b+1)) >> 1;
1794 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1795 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1796 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1798 pY = CLIP(pY, 0,255);
1799 pU = CLIP(pU, -127,127);
1800 pV = CLIP(pV, -127,127);
1802 if (i % 2){
1803 *yuv++ = (219 * pY)/255 + 16; // Y
1804 *yuv++ = (112 * pU)/127 + 128; // U
1806 else {
1807 *yuv++ = (219 * pY)/255 + 16; // Y
1808 *yuv++ = (112 * pV)/127 + 128; // V
1811 b += stepx;
1814 // Skip the last pixel
1815 *yuv++ = 16;
1816 *yuv++ = 128;
1818 else {
1819 // Skip the first pixel
1820 *yuv++ = 16;
1821 *yuv++ = 128;
1823 // RGRGRG : Line process...
1824 for (i=0, x=startx; i<nwidth-2; i++, x=x+stepx) {
1825 if (x & 0x1) {
1826 pR = (*(b-1) + *(b+1)) >> 1;
1827 pG = *b;
1828 pB = (*(b-width) + *(b+width)) >> 1;
1830 else {
1831 pR = *b;
1832 pG = (*(b-width) + *(b-1) + *(b+1) + *(b+width)) >> 2;
1833 pB = (*(b-width-1) + *(b-width+1) + *(b+width-1) + *(b+width+1)) >> 2;
1836 pY = microdia_yuv_interp[pR][0] + microdia_yuv_interp[pG][1] + microdia_yuv_interp[pB][2];
1837 pU = microdia_yuv_interp[pR][3] + microdia_yuv_interp[pG][4] + microdia_yuv_interp[pB][5];
1838 pV = microdia_yuv_interp[pR][5] + microdia_yuv_interp[pG][6] + microdia_yuv_interp[pB][7];
1840 pY = CLIP(pY, 0,255);
1841 pU = CLIP(pU, -127,127);
1842 pV = CLIP(pV, -127,127);
1844 if (i % 2){
1845 *yuv++ = (219 * pY)/255 + 16; // Y
1846 *yuv++ = (112 * pU)/127 + 128; // U
1848 else {
1849 *yuv++ = (219 * pY)/255 + 16; // Y
1850 *yuv++ = (112 * pV)/127 + 128; // V
1853 b += stepx;
1856 // Skip the last pixel
1857 *yuv++ = 16;
1858 *yuv++ = 128;
1862 // Clean the last line
1863 memset(yuv, 128, nwidth * 2);
1864 for (i=0; i<nwidth*2; i=i+2, *(yuv+i)=16);