summaryrefslogtreecommitdiff
path: root/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/lib/libv4l/libv4lconvert/bayer.c')
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/bayer.c613
1 files changed, 0 insertions, 613 deletions
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c b/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c
deleted file mode 100644
index ca7bb486f..000000000
--- a/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * lib4lconvert, video4linux2 format conversion lib
- * (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Note: original bayer_to_bgr24 code from :
- * 1394-Based Digital Camera Control Library
- *
- * Bayer pattern decoding functions
- *
- * Written by Damien Douxchamps and Frederic Devernay
- *
- * Note that the original bayer.c in libdc1394 supports many different
- * bayer decode algorithms, for lib4lconvert the one in this file has been
- * chosen (and optimized a bit) and the other algorithm's have been removed,
- * see bayer.c from libdc1394 for all supported algorithms
- */
-
-#include <string.h>
-#include "libv4lconvert-priv.h"
-
-/**************************************************************
- * Color conversion functions for cameras that can *
- * output raw-Bayer pattern images, such as some Basler and *
- * Point Grey camera. Most of the algos presented here come *
- * from http://www-ise.stanford.edu/~tingchen/ and have been *
- * converted from Matlab to C and extended to all elementary *
- * patterns. *
- **************************************************************/
-
-/* insprired by OpenCV's Bayer decoding */
-static void v4lconvert_border_bayer_line_to_bgr24(
- const unsigned char* bayer, const unsigned char* adjacent_bayer,
- unsigned char *bgr, int width, int start_with_green, int blue_line)
-{
- int t0, t1;
-
- if (start_with_green) {
- /* First pixel */
- if (blue_line) {
- *bgr++ = bayer[1];
- *bgr++ = bayer[0];
- *bgr++ = adjacent_bayer[0];
- } else {
- *bgr++ = adjacent_bayer[0];
- *bgr++ = bayer[0];
- *bgr++ = bayer[1];
- }
- /* Second pixel */
- t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
- t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
- if (blue_line) {
- *bgr++ = bayer[1];
- *bgr++ = t0;
- *bgr++ = t1;
- } else {
- *bgr++ = t1;
- *bgr++ = t0;
- *bgr++ = bayer[1];
- }
- bayer++;
- adjacent_bayer++;
- width -= 2;
- } else {
- /* First pixel */
- t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1;
- if (blue_line) {
- *bgr++ = bayer[0];
- *bgr++ = t0;
- *bgr++ = adjacent_bayer[1];
- } else {
- *bgr++ = adjacent_bayer[1];
- *bgr++ = t0;
- *bgr++ = bayer[0];
- }
- width--;
- }
-
- if (blue_line) {
- for ( ; width > 2; width -= 2) {
- t0 = (bayer[0] + bayer[2] + 1) >> 1;
- *bgr++ = t0;
- *bgr++ = bayer[1];
- *bgr++ = adjacent_bayer[1];
- bayer++;
- adjacent_bayer++;
-
- t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
- t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
- *bgr++ = bayer[1];
- *bgr++ = t0;
- *bgr++ = t1;
- bayer++;
- adjacent_bayer++;
- }
- } else {
- for ( ; width > 2; width -= 2) {
- t0 = (bayer[0] + bayer[2] + 1) >> 1;
- *bgr++ = adjacent_bayer[1];
- *bgr++ = bayer[1];
- *bgr++ = t0;
- bayer++;
- adjacent_bayer++;
-
- t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
- t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
- *bgr++ = t1;
- *bgr++ = t0;
- *bgr++ = bayer[1];
- bayer++;
- adjacent_bayer++;
- }
- }
-
- if (width == 2) {
- /* Second to last pixel */
- t0 = (bayer[0] + bayer[2] + 1) >> 1;
- if (blue_line) {
- *bgr++ = t0;
- *bgr++ = bayer[1];
- *bgr++ = adjacent_bayer[1];
- } else {
- *bgr++ = adjacent_bayer[1];
- *bgr++ = bayer[1];
- *bgr++ = t0;
- }
- /* Last pixel */
- t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1;
- if (blue_line) {
- *bgr++ = bayer[2];
- *bgr++ = t0;
- *bgr++ = adjacent_bayer[1];
- } else {
- *bgr++ = adjacent_bayer[1];
- *bgr++ = t0;
- *bgr++ = bayer[2];
- }
- } else {
- /* Last pixel */
- if (blue_line) {
- *bgr++ = bayer[0];
- *bgr++ = bayer[1];
- *bgr++ = adjacent_bayer[1];
- } else {
- *bgr++ = adjacent_bayer[1];
- *bgr++ = bayer[1];
- *bgr++ = bayer[0];
- }
- }
-}
-
-/* From libdc1394, which on turn was based on OpenCV's Bayer decoding */
-static void bayer_to_rgbbgr24(const unsigned char *bayer,
- unsigned char *bgr, int width, int height, unsigned int pixfmt,
- int start_with_green, int blue_line)
-{
- /* render the first line */
- v4lconvert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width,
- start_with_green, blue_line);
- bgr += width * 3;
-
- /* reduce height by 2 because of the special case top/bottom line */
- for (height -= 2; height; height--) {
- int t0, t1;
- /* (width - 2) because of the border */
- const unsigned char *bayerEnd = bayer + (width - 2);
-
- if (start_with_green) {
- /* OpenCV has a bug in the next line, which was
- t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; */
- t0 = (bayer[1] + bayer[width * 2 + 1] + 1) >> 1;
- /* Write first pixel */
- t1 = (bayer[0] + bayer[width * 2] + bayer[width + 1] + 1) / 3;
- if (blue_line) {
- *bgr++ = t0;
- *bgr++ = t1;
- *bgr++ = bayer[width];
- } else {
- *bgr++ = bayer[width];
- *bgr++ = t1;
- *bgr++ = t0;
- }
-
- /* Write second pixel */
- t1 = (bayer[width] + bayer[width + 2] + 1) >> 1;
- if (blue_line) {
- *bgr++ = t0;
- *bgr++ = bayer[width + 1];
- *bgr++ = t1;
- } else {
- *bgr++ = t1;
- *bgr++ = bayer[width + 1];
- *bgr++ = t0;
- }
- bayer++;
- } else {
- /* Write first pixel */
- t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
- if (blue_line) {
- *bgr++ = t0;
- *bgr++ = bayer[width];
- *bgr++ = bayer[width + 1];
- } else {
- *bgr++ = bayer[width + 1];
- *bgr++ = bayer[width];
- *bgr++ = t0;
- }
- }
-
- if (blue_line) {
- for (; bayer <= bayerEnd - 2; bayer += 2) {
- t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
- bayer[width * 2 + 2] + 2) >> 2;
- t1 = (bayer[1] + bayer[width] +
- bayer[width + 2] + bayer[width * 2 + 1] +
- 2) >> 2;
- *bgr++ = t0;
- *bgr++ = t1;
- *bgr++ = bayer[width + 1];
-
- t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
- t1 = (bayer[width + 1] + bayer[width + 3] +
- 1) >> 1;
- *bgr++ = t0;
- *bgr++ = bayer[width + 2];
- *bgr++ = t1;
- }
- } else {
- for (; bayer <= bayerEnd - 2; bayer += 2) {
- t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
- bayer[width * 2 + 2] + 2) >> 2;
- t1 = (bayer[1] + bayer[width] +
- bayer[width + 2] + bayer[width * 2 + 1] +
- 2) >> 2;
- *bgr++ = bayer[width + 1];
- *bgr++ = t1;
- *bgr++ = t0;
-
- t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
- t1 = (bayer[width + 1] + bayer[width + 3] +
- 1) >> 1;
- *bgr++ = t1;
- *bgr++ = bayer[width + 2];
- *bgr++ = t0;
- }
- }
-
- if (bayer < bayerEnd) {
- /* write second to last pixel */
- t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
- bayer[width * 2 + 2] + 2) >> 2;
- t1 = (bayer[1] + bayer[width] +
- bayer[width + 2] + bayer[width * 2 + 1] +
- 2) >> 2;
- if (blue_line) {
- *bgr++ = t0;
- *bgr++ = t1;
- *bgr++ = bayer[width + 1];
- } else {
- *bgr++ = bayer[width + 1];
- *bgr++ = t1;
- *bgr++ = t0;
- }
- /* write last pixel */
- t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
- if (blue_line) {
- *bgr++ = t0;
- *bgr++ = bayer[width + 2];
- *bgr++ = bayer[width + 1];
- } else {
- *bgr++ = bayer[width + 1];
- *bgr++ = bayer[width + 2];
- *bgr++ = t0;
- }
- bayer++;
- } else {
- /* write last pixel */
- t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
- t1 = (bayer[1] + bayer[width * 2 + 1] + bayer[width] + 1) / 3;
- if (blue_line) {
- *bgr++ = t0;
- *bgr++ = t1;
- *bgr++ = bayer[width + 1];
- } else {
- *bgr++ = bayer[width + 1];
- *bgr++ = t1;
- *bgr++ = t0;
- }
- }
-
- /* skip 2 border pixels */
- bayer += 2;
-
- blue_line = !blue_line;
- start_with_green = !start_with_green;
- }
-
- /* render the last line */
- v4lconvert_border_bayer_line_to_bgr24(bayer + width, bayer, bgr, width,
- !start_with_green, !blue_line);
-}
-
-void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
- unsigned char *bgr, int width, int height, unsigned int pixfmt)
-{
- bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt,
- pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */
- || pixfmt == V4L2_PIX_FMT_SGRBG8,
- pixfmt != V4L2_PIX_FMT_SBGGR8 /* blue line */
- && pixfmt != V4L2_PIX_FMT_SGBRG8);
-}
-
-void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
- unsigned char *bgr, int width, int height, unsigned int pixfmt)
-{
- bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt,
- pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */
- || pixfmt == V4L2_PIX_FMT_SGRBG8,
- pixfmt == V4L2_PIX_FMT_SBGGR8 /* blue line */
- || pixfmt == V4L2_PIX_FMT_SGBRG8);
-}
-
-static void 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)
-{
- int t0, t1;
-
- if (start_with_green) {
- /* First pixel */
- if (blue_line) {
- *y++ = (8453*adjacent_bayer[0] + 16594*bayer[0] + 3223*bayer[1] + 524288)
- >> 15;
- } else {
- *y++ = (8453*bayer[1] + 16594*bayer[0] + 3223*adjacent_bayer[0] + 524288)
- >> 15;
- }
- /* Second pixel */
- t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
- t1 = adjacent_bayer[0] + adjacent_bayer[2];
- if (blue_line) {
- *y++ = (4226*t1 + 5531*t0 + 3223*bayer[1] + 524288) >> 15;
- } else {
- *y++ = (8453*bayer[1] + 5531*t0 + 1611*t1 + 524288) >> 15;
- }
- bayer++;
- adjacent_bayer++;
- width -= 2;
- } else {
- /* First pixel */
- t0 = bayer[1] + adjacent_bayer[0];
- if (blue_line) {
- *y++ = (8453*adjacent_bayer[1] + 8297*t0 + 3223*bayer[0] + 524288)
- >> 15;
- } else {
- *y++ = (8453*bayer[0] + 8297*t0 + 3223*adjacent_bayer[1] + 524288)
- >> 15;
- }
- width--;
- }
-
- if (blue_line) {
- for ( ; width > 2; width -= 2) {
- t0 = bayer[0] + bayer[2];
- *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 1611*t0 + 524288)
- >> 15;
- bayer++;
- adjacent_bayer++;
-
- t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
- t1 = adjacent_bayer[0] + adjacent_bayer[2];
- *y++ = (4226*t1 + 5531*t0 + 3223*bayer[1] + 524288) >> 15;
- bayer++;
- adjacent_bayer++;
- }
- } else {
- for ( ; width > 2; width -= 2) {
- t0 = bayer[0] + bayer[2];
- *y++ = (4226*t0 + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288)
- >> 15;
- bayer++;
- adjacent_bayer++;
-
- t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
- t1 = adjacent_bayer[0] + adjacent_bayer[2];
- *y++ = (8453*bayer[1] + 5531*t0 + 1611*t1 + 524288) >> 15;
- bayer++;
- adjacent_bayer++;
- }
- }
-
- if (width == 2) {
- /* Second to last pixel */
- t0 = bayer[0] + bayer[2];
- if (blue_line) {
- *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 1611*t0 + 524288)
- >> 15;
- } else {
- *y++ = (4226*t0 + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288)
- >> 15;
- }
- /* Last pixel */
- t0 = bayer[1] + adjacent_bayer[2];
- if (blue_line) {
- *y++ = (8453*adjacent_bayer[1] + 8297*t0 + 3223*bayer[2] + 524288)
- >> 15;
- } else {
- *y++ = (8453*bayer[2] + 8297*t0 + 3223*adjacent_bayer[1] + 524288)
- >> 15;
- }
- } else {
- /* Last pixel */
- if (blue_line) {
- *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 3223*bayer[0] + 524288)
- >> 15;
- } else {
- *y++ = (8453*bayer[0] + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288)
- >> 15;
- }
- }
-}
-
-void v4lconvert_bayer_to_yuv420(const unsigned char *bayer,
- unsigned char *yuv, int width, int height, unsigned int pixfmt)
-{
- int blue_line = 0, start_with_green = 0, x, y;
- unsigned char *ydst = yuv;
- unsigned char *udst = yuv + width * height;
- unsigned char *vdst = udst + width * height / 4;
-
- /* First calculate the u and v planes 2x2 pixels at a time */
- switch (pixfmt) {
- case V4L2_PIX_FMT_SBGGR8:
- for (y = 0; y < height; y += 2) {
- for (x = 0; x < width; x += 2) {
- int b, g, r;
- b = bayer[x];
- g = bayer[x+1];
- g += bayer[x+width];
- r = bayer[x+width+1];
- *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
- *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
- }
- bayer += 2 * width;
- }
- blue_line = 1;
- break;
-
- case V4L2_PIX_FMT_SRGGB8:
- for (y = 0; y < height; y += 2) {
- for (x = 0; x < width; x += 2) {
- int b, g, r;
- r = bayer[x];
- g = bayer[x+1];
- g += bayer[x+width];
- b = bayer[x+width+1];
- *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
- *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
- }
- bayer += 2 * width;
- }
- break;
-
- case V4L2_PIX_FMT_SGBRG8:
- for (y = 0; y < height; y += 2) {
- for (x = 0; x < width; x += 2) {
- int b, g, r;
- g = bayer[x];
- b = bayer[x+1];
- r = bayer[x+width];
- g += bayer[x+width+1];
- *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
- *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
- }
- bayer += 2 * width;
- }
- blue_line = 1;
- start_with_green = 1;
- break;
-
- case V4L2_PIX_FMT_SGRBG8:
- for (y = 0; y < height; y += 2) {
- for (x = 0; x < width; x += 2) {
- int b, g, r;
- g = bayer[x];
- r = bayer[x+1];
- b = bayer[x+width];
- g += bayer[x+width+1];
- *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
- *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15;
- }
- bayer += 2 * width;
- }
- start_with_green = 1;
- break;
- }
-
- bayer -= width * height;
-
- /* render the first line */
- v4lconvert_border_bayer_line_to_y(bayer, bayer + width, ydst, width,
- start_with_green, blue_line);
- ydst += width;
-
- /* reduce height by 2 because of the border */
- for (height -= 2; height; height--) {
- int t0, t1;
- /* (width - 2) because of the border */
- const unsigned char *bayerEnd = bayer + (width - 2);
-
- if (start_with_green) {
- t0 = bayer[1] + bayer[width * 2 + 1];
- /* Write first pixel */
- t1 = bayer[0] + bayer[width * 2] + bayer[width + 1];
- if (blue_line)
- *ydst++ = (8453*bayer[width] + 5516*t1 + 1661*t0 + 524288) >> 15;
- else
- *ydst++ = (4226*t0 + 5516*t1 + 3223*bayer[width] + 524288) >> 15;
-
- /* Write second pixel */
- t1 = bayer[width] + bayer[width + 2];
- if (blue_line)
- *ydst++ = (4226*t1 + 16594*bayer[width+1] + 1611*t0 + 524288) >> 15;
- else
- *ydst++ = (4226*t0 + 16594*bayer[width+1] + 1611*t1 + 524288) >> 15;
- bayer++;
- } else {
- /* Write first pixel */
- t0 = bayer[0] + bayer[width * 2];
- if (blue_line) {
- *ydst++ = (8453*bayer[width+1] + 16594*bayer[width] + 1661*t0 +
- 524288) >> 15;
- } else {
- *ydst++ = (4226*t0 + 16594*bayer[width] + 3223*bayer[width+1] +
- 524288) >> 15;
- }
- }
-
- if (blue_line) {
- for (; bayer <= bayerEnd - 2; bayer += 2) {
- t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2];
- t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1];
- *ydst++ = (8453*bayer[width+1] + 4148*t1 + 806*t0 + 524288) >> 15;
-
- t0 = bayer[2] + bayer[width * 2 + 2];
- t1 = bayer[width + 1] + bayer[width + 3];
- *ydst++ = (4226*t1 + 16594*bayer[width+2] + 1611*t0 + 524288) >> 15;
- }
- } else {
- for (; bayer <= bayerEnd - 2; bayer += 2) {
- t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2];
- t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1];
- *ydst++ = (2113*t0 + 4148*t1 + 3223*bayer[width+1] + 524288) >> 15;
-
- t0 = bayer[2] + bayer[width * 2 + 2];
- t1 = bayer[width + 1] + bayer[width + 3];
- *ydst++ = (4226*t0 + 16594*bayer[width+2] + 1611*t1 + 524288) >> 15;
- }
- }
-
- if (bayer < bayerEnd) {
- /* Write second to last pixel */
- t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2];
- t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1];
- if (blue_line)
- *ydst++ = (8453*bayer[width+1] + 4148*t1 + 806*t0 + 524288) >> 15;
- else
- *ydst++ = (2113*t0 + 4148*t1 + 3223*bayer[width+1] + 524288) >> 15;
-
- /* write last pixel */
- t0 = bayer[2] + bayer[width * 2 + 2];
- if (blue_line) {
- *ydst++ = (8453*bayer[width+1] + 16594*bayer[width+2] + 1661*t0 +
- 524288) >> 15;
- } else {
- *ydst++ = (4226*t0 + 16594*bayer[width+2] + 3223*bayer[width+1] +
- 524288) >> 15;
- }
- bayer++;
- } else {
- /* write last pixel */
- t0 = bayer[0] + bayer[width * 2];
- t1 = bayer[1] + bayer[width * 2 + 1] + bayer[width];
- if (blue_line)
- *ydst++ = (8453*bayer[width+1] + 5516*t1 + 1661*t0 + 524288) >> 15;
- else
- *ydst++ = (4226*t0 + 5516*t1 + 3223*bayer[width+1] + 524288) >> 15;
- }
-
- /* skip 2 border pixels */
- bayer += 2;
-
- blue_line = !blue_line;
- start_with_green = !start_with_green;
- }
-
- /* render the last line */
- v4lconvert_border_bayer_line_to_y(bayer + width, bayer, ydst, width,
- !start_with_green, !blue_line);
-}