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