1 /*
2 * lib4lconvert, video4linux2 format conversion lib
3 * (C) 2008 Hans de Goede <hdegoede@redhat.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
18 *
19 * Note: original bayer_to_bgr24 code from :
20 * 1394-Based Digital Camera Control Library
21 *
22 * Bayer pattern decoding functions
23 *
24 * Written by Damien Douxchamps and Frederic Devernay
25 *
26 * Note that the original bayer.c in libdc1394 supports many different
27 * bayer decode algorithms, for lib4lconvert the one in this file has been
28 * chosen (and optimized a bit) and the other algorithms have been removed,
29 * see bayer.c from libdc1394 for all supported algorithms
30 */
31
32 #include <string.h>
33 #include "libv4lconvert-priv.h"
34
35 /**************************************************************
36 * Color conversion functions for cameras that can *
37 * output raw-Bayer pattern images, such as some Basler and *
38 * Point Grey camera. Most of the algos presented here come *
39 * from http://www-ise.stanford.edu/~tingchen/ and have been *
40 * converted from Matlab to C and extended to all elementary *
41 * patterns. *
42 **************************************************************/
43
44 /* inspired by OpenCV's Bayer decoding */
v4lconvert_border_bayer_line_to_bgr24(const unsigned char * bayer,const unsigned char * adjacent_bayer,unsigned char * bgr,int width,const int start_with_green,const int blue_line)45 static void v4lconvert_border_bayer_line_to_bgr24(
46 const unsigned char *bayer, const unsigned char *adjacent_bayer,
47 unsigned char *bgr, int width, const int start_with_green, const int blue_line)
48 {
49 int t0, t1;
50
51 if (start_with_green) {
52 /* First pixel */
53 if (blue_line) {
54 *bgr++ = bayer[1];
55 *bgr++ = bayer[0];
56 *bgr++ = adjacent_bayer[0];
57 } else {
58 *bgr++ = adjacent_bayer[0];
59 *bgr++ = bayer[0];
60 *bgr++ = bayer[1];
61 }
62 /* Second pixel */
63 t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
64 t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
65 if (blue_line) {
66 *bgr++ = bayer[1];
67 *bgr++ = t0;
68 *bgr++ = t1;
69 } else {
70 *bgr++ = t1;
71 *bgr++ = t0;
72 *bgr++ = bayer[1];
73 }
74 bayer++;
75 adjacent_bayer++;
76 width -= 2;
77 } else {
78 /* First pixel */
79 t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1;
80 if (blue_line) {
81 *bgr++ = bayer[0];
82 *bgr++ = t0;
83 *bgr++ = adjacent_bayer[1];
84 } else {
85 *bgr++ = adjacent_bayer[1];
86 *bgr++ = t0;
87 *bgr++ = bayer[0];
88 }
89 width--;
90 }
91
92 if (blue_line) {
93 for ( ; width > 2; width -= 2) {
94 t0 = (bayer[0] + bayer[2] + 1) >> 1;
95 *bgr++ = t0;
96 *bgr++ = bayer[1];
97 *bgr++ = adjacent_bayer[1];
98 bayer++;
99 adjacent_bayer++;
100
101 t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
102 t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
103 *bgr++ = bayer[1];
104 *bgr++ = t0;
105 *bgr++ = t1;
106 bayer++;
107 adjacent_bayer++;
108 }
109 } else {
110 for ( ; width > 2; width -= 2) {
111 t0 = (bayer[0] + bayer[2] + 1) >> 1;
112 *bgr++ = adjacent_bayer[1];
113 *bgr++ = bayer[1];
114 *bgr++ = t0;
115 bayer++;
116 adjacent_bayer++;
117
118 t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
119 t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
120 *bgr++ = t1;
121 *bgr++ = t0;
122 *bgr++ = bayer[1];
123 bayer++;
124 adjacent_bayer++;
125 }
126 }
127
128 if (width == 2) {
129 /* Second to last pixel */
130 t0 = (bayer[0] + bayer[2] + 1) >> 1;
131 if (blue_line) {
132 *bgr++ = t0;
133 *bgr++ = bayer[1];
134 *bgr++ = adjacent_bayer[1];
135 } else {
136 *bgr++ = adjacent_bayer[1];
137 *bgr++ = bayer[1];
138 *bgr++ = t0;
139 }
140 /* Last pixel */
141 t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1;
142 if (blue_line) {
143 *bgr++ = bayer[2];
144 *bgr++ = t0;
145 *bgr++ = adjacent_bayer[1];
146 } else {
147 *bgr++ = adjacent_bayer[1];
148 *bgr++ = t0;
149 *bgr++ = bayer[2];
150 }
151 } else {
152 /* Last pixel */
153 if (blue_line) {
154 *bgr++ = bayer[0];
155 *bgr++ = bayer[1];
156 *bgr++ = adjacent_bayer[1];
157 } else {
158 *bgr++ = adjacent_bayer[1];
159 *bgr++ = bayer[1];
160 *bgr++ = bayer[0];
161 }
162 }
163 }
164
165 /* From libdc1394, which on turn was based on OpenCV's Bayer decoding */
bayer_to_rgbbgr24(const unsigned char * bayer,unsigned char * bgr,int width,int height,const unsigned int stride,unsigned int pixfmt,int start_with_green,int blue_line)166 static void bayer_to_rgbbgr24(const unsigned char *bayer,
167 unsigned char *bgr, int width, int height, const unsigned int stride, unsigned int pixfmt,
168 int start_with_green, int blue_line)
169 {
170 /* render the first line */
171 v4lconvert_border_bayer_line_to_bgr24(bayer, bayer + stride, bgr, width,
172 start_with_green, blue_line);
173 bgr += width * 3;
174
175 /* reduce height by 2 because of the special case top/bottom line */
176 for (height -= 2; height; height--) {
177 int t0, t1;
178 /* (width - 2) because of the border */
179 const unsigned char *bayer_end = bayer + (width - 2);
180
181 if (start_with_green) {
182
183 t0 = (bayer[1] + bayer[stride * 2 + 1] + 1) >> 1;
184 /* Write first pixel */
185 t1 = (bayer[0] + bayer[stride * 2] + bayer[stride + 1] + 1) / 3;
186 if (blue_line) {
187 *bgr++ = t0;
188 *bgr++ = t1;
189 *bgr++ = bayer[stride];
190 } else {
191 *bgr++ = bayer[stride];
192 *bgr++ = t1;
193 *bgr++ = t0;
194 }
195
196 /* Write second pixel */
197 t1 = (bayer[stride] + bayer[stride + 2] + 1) >> 1;
198 if (blue_line) {
199 *bgr++ = t0;
200 *bgr++ = bayer[stride + 1];
201 *bgr++ = t1;
202 } else {
203 *bgr++ = t1;
204 *bgr++ = bayer[stride + 1];
205 *bgr++ = t0;
206 }
207 bayer++;
208 } else {
209 /* Write first pixel */
210 t0 = (bayer[0] + bayer[stride * 2] + 1) >> 1;
211 if (blue_line) {
212 *bgr++ = t0;
213 *bgr++ = bayer[stride];
214 *bgr++ = bayer[stride + 1];
215 } else {
216 *bgr++ = bayer[stride + 1];
217 *bgr++ = bayer[stride];
218 *bgr++ = t0;
219 }
220 }
221
222 if (blue_line) {
223 for (; bayer <= bayer_end - 2; bayer += 2) {
224 t0 = (bayer[0] + bayer[2] + bayer[stride * 2] +
225 bayer[stride * 2 + 2] + 2) >> 2;
226 t1 = (bayer[1] + bayer[stride] + bayer[stride + 2] +
227 bayer[stride * 2 + 1] + 2) >> 2;
228 *bgr++ = t0;
229 *bgr++ = t1;
230 *bgr++ = bayer[stride + 1];
231
232 t0 = (bayer[2] + bayer[stride * 2 + 2] + 1) >> 1;
233 t1 = (bayer[stride + 1] + bayer[stride + 3] + 1) >> 1;
234 *bgr++ = t0;
235 *bgr++ = bayer[stride + 2];
236 *bgr++ = t1;
237 }
238 } else {
239 for (; bayer <= bayer_end - 2; bayer += 2) {
240 t0 = (bayer[0] + bayer[2] + bayer[stride * 2] +
241 bayer[stride * 2 + 2] + 2) >> 2;
242 t1 = (bayer[1] + bayer[stride] + bayer[stride + 2] +
243 bayer[stride * 2 + 1] + 2) >> 2;
244 *bgr++ = bayer[stride + 1];
245 *bgr++ = t1;
246 *bgr++ = t0;
247
248 t0 = (bayer[2] + bayer[stride * 2 + 2] + 1) >> 1;
249 t1 = (bayer[stride + 1] + bayer[stride + 3] + 1) >> 1;
250 *bgr++ = t1;
251 *bgr++ = bayer[stride + 2];
252 *bgr++ = t0;
253 }
254 }
255
256 if (bayer < bayer_end) {
257 /* write second to last pixel */
258 t0 = (bayer[0] + bayer[2] + bayer[stride * 2] +
259 bayer[stride * 2 + 2] + 2) >> 2;
260 t1 = (bayer[1] + bayer[stride] + bayer[stride + 2] +
261 bayer[stride * 2 + 1] + 2) >> 2;
262 if (blue_line) {
263 *bgr++ = t0;
264 *bgr++ = t1;
265 *bgr++ = bayer[stride + 1];
266 } else {
267 *bgr++ = bayer[stride + 1];
268 *bgr++ = t1;
269 *bgr++ = t0;
270 }
271 /* write last pixel */
272 t0 = (bayer[2] + bayer[stride * 2 + 2] + 1) >> 1;
273 if (blue_line) {
274 *bgr++ = t0;
275 *bgr++ = bayer[stride + 2];
276 *bgr++ = bayer[stride + 1];
277 } else {
278 *bgr++ = bayer[stride + 1];
279 *bgr++ = bayer[stride + 2];
280 *bgr++ = t0;
281 }
282
283 bayer++;
284
285 } else {
286 /* write last pixel */
287 t0 = (bayer[0] + bayer[stride * 2] + 1) >> 1;
288 t1 = (bayer[1] + bayer[stride * 2 + 1] + bayer[stride] + 1) / 3;
289 if (blue_line) {
290 *bgr++ = t0;
291 *bgr++ = t1;
292 *bgr++ = bayer[stride + 1];
293 } else {
294 *bgr++ = bayer[stride + 1];
295 *bgr++ = t1;
296 *bgr++ = t0;
297 }
298
299 }
300
301 /* skip 2 border pixels and padding */
302 bayer += (stride - width) + 2;
303
304 blue_line = !blue_line;
305 start_with_green = !start_with_green;
306 }
307
308 /* render the last line */
309 v4lconvert_border_bayer_line_to_bgr24(bayer + stride, bayer, bgr, width,
310 !start_with_green, !blue_line);
311 }
312
v4lconvert_bayer_to_rgb24(const unsigned char * bayer,unsigned char * bgr,int width,int height,const unsigned int stride,unsigned int pixfmt)313 void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
314 unsigned char *bgr, int width, int height, const unsigned int stride, unsigned int pixfmt)
315 {
316 bayer_to_rgbbgr24(bayer, bgr, width, height, stride, pixfmt,
317 pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */
318 || pixfmt == V4L2_PIX_FMT_SGRBG8,
319 pixfmt != V4L2_PIX_FMT_SBGGR8 /* blue line */
320 && pixfmt != V4L2_PIX_FMT_SGBRG8);
321 }
322
v4lconvert_bayer_to_bgr24(const unsigned char * bayer,unsigned char * bgr,int width,int height,const unsigned int stride,unsigned int pixfmt)323 void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
324 unsigned char *bgr, int width, int height, const unsigned int stride, unsigned int pixfmt)
325 {
326 bayer_to_rgbbgr24(bayer, bgr, width, height, stride, pixfmt,
327 pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */
328 || pixfmt == V4L2_PIX_FMT_SGRBG8,
329 pixfmt == V4L2_PIX_FMT_SBGGR8 /* blue line */
330 || pixfmt == V4L2_PIX_FMT_SGBRG8);
331 }
332
v4lconvert_border_bayer_line_to_y(const unsigned char * bayer,const unsigned char * adjacent_bayer,unsigned char * y,int width,int start_with_green,int blue_line)333 static void v4lconvert_border_bayer_line_to_y(
334 const unsigned char *bayer, const unsigned char *adjacent_bayer,
335 unsigned char *y, int width, int start_with_green, int blue_line)
336 {
337 int t0, t1;
338
339 if (start_with_green) {
340 /* First pixel */
341 if (blue_line) {
342 *y++ = (8453 * adjacent_bayer[0] + 16594 * bayer[0] +
343 3223 * bayer[1] + 524288) >> 15;
344 } else {
345 *y++ = (8453 * bayer[1] + 16594 * bayer[0] +
346 3223 * adjacent_bayer[0] + 524288) >> 15;
347 }
348 /* Second pixel */
349 t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
350 t1 = adjacent_bayer[0] + adjacent_bayer[2];
351 if (blue_line)
352 *y++ = (4226 * t1 + 5531 * t0 + 3223 * bayer[1] + 524288) >> 15;
353 else
354 *y++ = (8453 * bayer[1] + 5531 * t0 + 1611 * t1 + 524288) >> 15;
355 bayer++;
356 adjacent_bayer++;
357 width -= 2;
358 } else {
359 /* First pixel */
360 t0 = bayer[1] + adjacent_bayer[0];
361 if (blue_line) {
362 *y++ = (8453 * adjacent_bayer[1] + 8297 * t0 +
363 3223 * bayer[0] + 524288) >> 15;
364 } else {
365 *y++ = (8453 * bayer[0] + 8297 * t0 +
366 3223 * adjacent_bayer[1] + 524288) >> 15;
367 }
368 width--;
369 }
370
371 if (blue_line) {
372 for ( ; width > 2; width -= 2) {
373 t0 = bayer[0] + bayer[2];
374 *y++ = (8453 * adjacent_bayer[1] + 16594 * bayer[1] +
375 1611 * t0 + 524288) >> 15;
376 bayer++;
377 adjacent_bayer++;
378
379 t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
380 t1 = adjacent_bayer[0] + adjacent_bayer[2];
381 *y++ = (4226 * t1 + 5531 * t0 + 3223 * bayer[1] + 524288) >> 15;
382 bayer++;
383 adjacent_bayer++;
384 }
385 } else {
386 for ( ; width > 2; width -= 2) {
387 t0 = bayer[0] + bayer[2];
388 *y++ = (4226 * t0 + 16594 * bayer[1] +
389 3223 * adjacent_bayer[1] + 524288) >> 15;
390 bayer++;
391 adjacent_bayer++;
392
393 t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
394 t1 = adjacent_bayer[0] + adjacent_bayer[2];
395 *y++ = (8453 * bayer[1] + 5531 * t0 + 1611 * t1 + 524288) >> 15;
396 bayer++;
397 adjacent_bayer++;
398 }
399 }
400
401 if (width == 2) {
402 /* Second to last pixel */
403 t0 = bayer[0] + bayer[2];
404 if (blue_line) {
405 *y++ = (8453 * adjacent_bayer[1] + 16594 * bayer[1] +
406 1611 * t0 + 524288) >> 15;
407 } else {
408 *y++ = (4226 * t0 + 16594 * bayer[1] +
409 3223 * adjacent_bayer[1] + 524288) >> 15;
410 }
411 /* Last pixel */
412 t0 = bayer[1] + adjacent_bayer[2];
413 if (blue_line) {
414 *y++ = (8453 * adjacent_bayer[1] + 8297 * t0 +
415 3223 * bayer[2] + 524288) >> 15;
416 } else {
417 *y++ = (8453 * bayer[2] + 8297 * t0 +
418 3223 * adjacent_bayer[1] + 524288) >> 15;
419 }
420 } else {
421 /* Last pixel */
422 if (blue_line) {
423 *y++ = (8453 * adjacent_bayer[1] + 16594 * bayer[1] +
424 3223 * bayer[0] + 524288) >> 15;
425 } else {
426 *y++ = (8453 * bayer[0] + 16594 * bayer[1] +
427 3223 * adjacent_bayer[1] + 524288) >> 15;
428 }
429 }
430 }
431
v4lconvert_bayer_to_yuv420(const unsigned char * bayer,unsigned char * yuv,int width,int height,const unsigned int stride,unsigned int src_pixfmt,int yvu)432 void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char *yuv,
433 int width, int height, const unsigned int stride, unsigned int src_pixfmt, int yvu)
434 {
435 int blue_line = 0, start_with_green = 0, x, y;
436 unsigned char *ydst = yuv;
437 unsigned char *udst, *vdst;
438
439 if (yvu) {
440 vdst = yuv + width * height;
441 udst = vdst + width * height / 4;
442 } else {
443 udst = yuv + width * height;
444 vdst = udst + width * height / 4;
445 }
446
447 /* First calculate the u and v planes 2x2 pixels at a time */
448 switch (src_pixfmt) {
449 case V4L2_PIX_FMT_SBGGR8:
450 for (y = 0; y < height; y += 2) {
451 for (x = 0; x < width; x += 2) {
452 int b, g, r;
453
454 b = bayer[x];
455 g = bayer[x + 1];
456 g += bayer[x + stride];
457 r = bayer[x + stride + 1];
458 *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
459 *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
460 }
461 bayer += 2 * stride;
462 }
463 blue_line = 1;
464 break;
465
466 case V4L2_PIX_FMT_SRGGB8:
467 for (y = 0; y < height; y += 2) {
468 for (x = 0; x < width; x += 2) {
469 int b, g, r;
470
471 r = bayer[x];
472 g = bayer[x + 1];
473 g += bayer[x + stride];
474 b = bayer[x + stride + 1];
475 *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
476 *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
477 }
478 bayer += 2 * stride;
479 }
480 break;
481
482 case V4L2_PIX_FMT_SGBRG8:
483 for (y = 0; y < height; y += 2) {
484 for (x = 0; x < width; x += 2) {
485 int b, g, r;
486
487 g = bayer[x];
488 b = bayer[x + 1];
489 r = bayer[x + stride];
490 g += bayer[x + stride + 1];
491 *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
492 *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
493 }
494 bayer += 2 * stride;
495 }
496 blue_line = 1;
497 start_with_green = 1;
498 break;
499
500 case V4L2_PIX_FMT_SGRBG8:
501 for (y = 0; y < height; y += 2) {
502 for (x = 0; x < width; x += 2) {
503 int b, g, r;
504
505 g = bayer[x];
506 r = bayer[x + 1];
507 b = bayer[x + stride];
508 g += bayer[x + stride + 1];
509 *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
510 *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
511 }
512 bayer += 2 * stride;
513 }
514 start_with_green = 1;
515 break;
516 }
517
518 /* Point bayer back to start of frame */
519 bayer -= stride * height;
520
521 /* render the first line */
522 v4lconvert_border_bayer_line_to_y(bayer, bayer + stride, ydst, width,
523 start_with_green, blue_line);
524 ydst += width;
525
526 /* reduce height by 2 because of the border */
527 for (height -= 2; height; height--) {
528 int t0, t1;
529 /* (width - 2) because of the border */
530 const unsigned char *bayer_end = bayer + (width - 2);
531
532 if (start_with_green) {
533 t0 = bayer[1] + bayer[stride * 2 + 1];
534 /* Write first pixel */
535 t1 = bayer[0] + bayer[stride * 2] + bayer[stride + 1];
536 if (blue_line)
537 *ydst++ = (8453 * bayer[stride] + 5516 * t1 +
538 1661 * t0 + 524288) >> 15;
539 else
540 *ydst++ = (4226 * t0 + 5516 * t1 +
541 3223 * bayer[stride] + 524288) >> 15;
542
543 /* Write second pixel */
544 t1 = bayer[stride] + bayer[stride + 2];
545 if (blue_line)
546 *ydst++ = (4226 * t1 + 16594 * bayer[stride + 1] +
547 1611 * t0 + 524288) >> 15;
548 else
549 *ydst++ = (4226 * t0 + 16594 * bayer[stride + 1] +
550 1611 * t1 + 524288) >> 15;
551 bayer++;
552 } else {
553 /* Write first pixel */
554 t0 = bayer[0] + bayer[stride * 2];
555 if (blue_line) {
556 *ydst++ = (8453 * bayer[stride + 1] + 16594 * bayer[stride] +
557 1661 * t0 + 524288) >> 15;
558 } else {
559 *ydst++ = (4226 * t0 + 16594 * bayer[stride] +
560 3223 * bayer[stride + 1] + 524288) >> 15;
561 }
562 }
563
564 if (blue_line) {
565 for (; bayer <= bayer_end - 2; bayer += 2) {
566 t0 = bayer[0] + bayer[2] + bayer[stride * 2] + bayer[stride * 2 + 2];
567 t1 = bayer[1] + bayer[stride] + bayer[stride + 2] + bayer[stride * 2 + 1];
568 *ydst++ = (8453 * bayer[stride + 1] + 4148 * t1 +
569 806 * t0 + 524288) >> 15;
570
571 t0 = bayer[2] + bayer[stride * 2 + 2];
572 t1 = bayer[stride + 1] + bayer[stride + 3];
573 *ydst++ = (4226 * t1 + 16594 * bayer[stride + 2] +
574 1611 * t0 + 524288) >> 15;
575 }
576 } else {
577 for (; bayer <= bayer_end - 2; bayer += 2) {
578 t0 = bayer[0] + bayer[2] + bayer[stride * 2] + bayer[stride * 2 + 2];
579 t1 = bayer[1] + bayer[stride] + bayer[stride + 2] + bayer[stride * 2 + 1];
580 *ydst++ = (2113 * t0 + 4148 * t1 +
581 3223 * bayer[stride + 1] + 524288) >> 15;
582
583 t0 = bayer[2] + bayer[stride * 2 + 2];
584 t1 = bayer[stride + 1] + bayer[stride + 3];
585 *ydst++ = (4226 * t0 + 16594 * bayer[stride + 2] +
586 1611 * t1 + 524288) >> 15;
587 }
588 }
589
590 if (bayer < bayer_end) {
591 /* Write second to last pixel */
592 t0 = bayer[0] + bayer[2] + bayer[stride * 2] + bayer[stride * 2 + 2];
593 t1 = bayer[1] + bayer[stride] + bayer[stride + 2] + bayer[stride * 2 + 1];
594 if (blue_line)
595 *ydst++ = (8453 * bayer[stride + 1] + 4148 * t1 +
596 806 * t0 + 524288) >> 15;
597 else
598 *ydst++ = (2113 * t0 + 4148 * t1 +
599 3223 * bayer[stride + 1] + 524288) >> 15;
600
601 /* write last pixel */
602 t0 = bayer[2] + bayer[stride * 2 + 2];
603 if (blue_line) {
604 *ydst++ = (8453 * bayer[stride + 1] + 16594 * bayer[stride + 2] +
605 1661 * t0 + 524288) >> 15;
606 } else {
607 *ydst++ = (4226 * t0 + 16594 * bayer[stride + 2] +
608 3223 * bayer[stride + 1] + 524288) >> 15;
609 }
610 bayer++;
611 } else {
612 /* write last pixel */
613 t0 = bayer[0] + bayer[stride * 2];
614 t1 = bayer[1] + bayer[stride * 2 + 1] + bayer[stride];
615 if (blue_line)
616 *ydst++ = (8453 * bayer[stride + 1] + 5516 * t1 +
617 1661 * t0 + 524288) >> 15;
618 else
619 *ydst++ = (4226 * t0 + 5516 * t1 +
620 3223 * bayer[stride + 1] + 524288) >> 15;
621 }
622
623 /* skip 2 border pixels and padding */
624 bayer += (stride - width) + 2;
625
626 blue_line = !blue_line;
627 start_with_green = !start_with_green;
628 }
629
630 /* render the last line */
631 v4lconvert_border_bayer_line_to_y(bayer + stride, bayer, ydst, width,
632 !start_with_green, !blue_line);
633 }
634
v4lconvert_bayer10_to_bayer8(void * bayer10,unsigned char * bayer8,int width,int height)635 void v4lconvert_bayer10_to_bayer8(void *bayer10,
636 unsigned char *bayer8, int width, int height)
637 {
638 int i;
639 uint16_t *src = bayer10;
640
641 for (i = 0; i < width * height; i++)
642 bayer8[i] = src[i] >> 2;
643 }
644
v4lconvert_bayer10p_to_bayer8(unsigned char * bayer10p,unsigned char * bayer8,int width,int height)645 void v4lconvert_bayer10p_to_bayer8(unsigned char *bayer10p,
646 unsigned char *bayer8, int width, int height)
647 {
648 unsigned long i;
649 unsigned long len = width * height;
650
651 for (i = 0; i < len ; i += 4) {
652 /*
653 * Do not use a second loop, hoping that
654 * a clever compiler with understand the
655 * pattern and will optimize it.
656 */
657 bayer8[0] = bayer10p[0];
658 bayer8[1] = bayer10p[1];
659 bayer8[2] = bayer10p[2];
660 bayer8[3] = bayer10p[3];
661 bayer10p += 5;
662 bayer8 += 4;
663 }
664 }
665
v4lconvert_bayer16_to_bayer8(unsigned char * bayer16,unsigned char * bayer8,int width,int height)666 void v4lconvert_bayer16_to_bayer8(unsigned char *bayer16,
667 unsigned char *bayer8, int width, int height)
668 {
669 int i;
670
671 for (i = 0; i < width * height; i++)
672 bayer8[i] = bayer16[2*i+1];
673 }
674