您的位置:首页 > 其它

【VS开发】【图像处理】 bayer, yuv, RGB转换方法

2016-07-24 08:37 411 查看
因为我的STVxxx USB camera输出格式是bayer格式,手头上只有YUVTOOLS这个查看工具,没法验证STVxxx在开发板上是否正常工作。
网上找了很久也没找到格式转换工具,最后放弃了,觉得还是写个转换工具比较快。抄写了部分libv4lconvert的代码, 我只验证了

V4L2_PIX_FMT_SGBRG8到V4L2_PIX_FMT_YUV420的转换。

bayer.c
##################################################################################

[cpp] view
plain copy

/*

* lib4lconvert, video4linux2 format conversion lib

* (C) 2008 Hans de Goede <hdegoede@redhat.com>

*

* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 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 <linux/videodev2.h>

#include <stdio.h>

#include "convert.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. *

**************************************************************/

/* inspired 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;

return;

/* 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 *bayer_end = 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 <= bayer_end - 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 <= bayer_end - 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 < bayer_end) {

/* 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 src_pixfmt, int yvu)

{

int blue_line = 0, start_with_green = 0, x, y;

unsigned char *ydst = yuv;

unsigned char *udst, *vdst;

if (yvu) {

vdst = yuv + width * height;

udst = vdst + width * height / 4;

} else {

udst = yuv + width * height;

vdst = udst + width * height / 4;

}

printf("bayer address(0x%p)", bayer);

/* First calculate the u and v planes 2x2 pixels at a time */

switch (src_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;

printf("bayer address(0x%p)", bayer);

/* render the first line */

v4lconvert_border_bayer_line_to_y(bayer, bayer + width, ydst, width,

start_with_green, blue_line);

ydst += width;

printf("bayer address(0x%p), height(%d)", bayer, height);

/* 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 *bayer_end = 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 <= bayer_end - 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 <= bayer_end - 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 < bayer_end) {

/* 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);

}

##################################################################################

convert.c
##################################################################################

[cpp] view
plain copy

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <linux/videodev2.h>

#include "convert.h"

char *g_src_file = NULL;

char *g_dest_file = NULL;

int g_in_width = 352;

int g_in_height = 292;

unsigned int g_src_fmt = V4L2_PIX_FMT_SGBRG8;

//unsigned int g_dest_fmt = V4L2_PIX_FMT_RGB24;

unsigned int g_dest_fmt = V4L2_PIX_FMT_YUV420;

int process_cmdline(int argc, char **argv)

{

int i;

char *tmp;

for (i = 1; i < argc; i++) {

if (strcmp(argv[i], "-s") == 0) {

g_src_file = argv[++i];

}

else if (strcmp(argv[i], "d") == 0) {

g_dest_file = strdup(argv[++i]);

}

else if (strcmp(argv[i], "-sf") == 0) {

tmp = argv[++i];

if (strlen(tmp) == 4) {

g_src_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);

}

}

else if (strcmp(argv[i], "-df") == 0) {

tmp = argv[++i];

if (strlen(tmp) == 4) {

g_dest_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);

}

}

else if (strcmp(argv[i], "iw") == 0) {

g_in_width = atoi(argv[++i]);

}

else if (strcmp(argv[i], "ih") == 0) {

g_in_height = atoi(argv[++i]);

}

}

if (g_src_file && g_dest_file == NULL) {

g_dest_file = malloc(256);

sprintf(g_dest_file, "%s.out", g_src_file);

}

if (g_in_width == 0 || g_in_height == 0) {

}

}

int get_file_size(int fd)

{

int ret;

struct stat sb;

ret = fstat(fd, &sb);

if (ret == -1) {

return ret;

}

return sb.st_size;

}

int get_bits_per_pixel(unsigned int fmt)

{

int ret;

switch (fmt) {

case V4L2_PIX_FMT_RGB24:

ret = 24;

break;

case V4L2_PIX_FMT_SBGGR8:

case V4L2_PIX_FMT_SGBRG8:

case V4L2_PIX_FMT_SGRBG8:

case V4L2_PIX_FMT_SRGGB8:

ret = 8;

break;

case V4L2_PIX_FMT_YUV420:

ret = 12;

break;

case V4L2_PIX_FMT_YUYV:

case V4L2_PIX_FMT_UYVY:

ret = 16;

break;

default:

ret = -1;

break;

}

return ret;

}

void convert(void *src, void *dest, int width, int height, unsigned int src_fmt, unsigned int dest_fmt)

{

switch (src_fmt) {

case V4L2_PIX_FMT_SGBRG8:

if (dest_fmt == V4L2_PIX_FMT_RGB24) {

v4lconvert_bayer_to_rgb24(src, dest, width, height, src_fmt);

}

else if (dest_fmt == V4L2_PIX_FMT_YUV420) {

v4lconvert_bayer_to_yuv420(src, dest, width, height, src_fmt, 0);

}

break;

default:

break;

}

}

int main(int argc, char *argv[])

{

int ret = 0;

int fd_src = 0;

int fd_dest = 0;

int src_size = 0;

int dest_size = 0;

int pix_num;

void *src = NULL;

void *dest = NULL;

process_cmdline(argc, argv);

if (g_src_file == NULL || g_dest_file == NULL) {

ret = -1;

goto bailout;

}

printf("input file(%s), output file(%s)\n", g_src_file, g_dest_file);

fd_src = open(g_src_file, O_RDONLY);

if (fd_src == -1) {

ret = -2;

goto bailout;

}

fd_dest = open(g_dest_file, O_RDWR | O_CREAT, 0666);

if (fd_dest == -1) {

ret = -3;

goto bailout;

}

src_size = get_file_size(fd_src);

if (src_size == -1) {

ret = -4;

goto bailout;

}

pix_num = src_size / (get_bits_per_pixel(g_src_fmt)/8) ;

//dest_size = pix_num * get_bytes_per_pixel(g_dest_fmt);

ret = get_bits_per_pixel(g_dest_fmt);

dest_size = pix_num * ret / 8;

printf("src_size(%d), dest_size(%d)\n", src_size, dest_size);

src = malloc(src_size);

dest = malloc(dest_size);

if (src == NULL || dest == NULL) {

ret = -5;

goto bailout;

}

ret = read(fd_src, src, src_size);

if (ret != src_size) {

ret = -6;

goto bailout;

}

convert(src, dest, g_in_width, g_in_height, g_src_fmt, g_dest_fmt);

printf("write out file, size=%d\n", dest_size);

ret = write(fd_dest, dest, dest_size);

if (ret != dest_size) {

ret = -1;

goto bailout;

}

bailout:

if (src)

free(src);

if (dest)

free(dest);

if (fd_src)

close(fd_src);

if (fd_dest)

close(fd_dest);

if (g_dest_file)

free(g_dest_file);

printf("ret(%d)\n", ret);

return ret;

}

##################################################################################


covert.h
##################################################################################



[cpp] view
plain copy

#ifndef __LIBV4LCONVERT_PRIV_H

#define __LIBV4LCONVERT_PRIV_H

#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B')

void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,

unsigned char *bgr, int width, int height, unsigned int pixfmt);

void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,

unsigned char *bgr, int width, int height, unsigned int pixfmt);

void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char *yuv,

int width, int height, unsigned int src_pixfmt, int yvu);

#endif /* __LIBV4LCONVERT_PRIV_H */

##################################################################################


Makefile
##################################################################################

[cpp] view
plain copy

CONVERT := convert

CFLAGS := -static

CC = gcc

$(CONVERT): convert.c bayer.c

$(CC) -o $@ $^ $(CFLAGS)

clean:

rm -f *.o $(CONVERT)

##################################################################################

RGB32 RGB565转换为YUV444
另外为了在PC显示framebuffer中的数据,写了一个ARGB32或者RGB565到YUV444的转换工具。利用YUVtools显示YUV444图像。
其实可以不用这么麻烦,使用ddms截屏也行。
YUV444是 Y U V分量比为4:4:4,每个像素用24bits表示。

##################################################################################

[cpp] view
plain copy

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <linux/videodev2.h>

char *g_src_file = NULL;

char *g_dest_file = NULL;

int g_in_width = 720;

int g_in_height = 480;

/* V4L2_PIX_FMT_BGR32 */

//unsigned int g_src_fmt = V4L2_PIX_FMT_RGB32;

unsigned int g_src_fmt = V4L2_PIX_FMT_RGB565;

/* V4L2_PIX_FMT_YUYV V4L2_PIX_FMT_YVYU V4L2_PIX_FMT_UYVY V4L2_PIX_FMT_VYUY */

unsigned int g_dest_fmt = V4L2_PIX_FMT_YUV444;

static unsigned char get_R(unsigned char *src, unsigned int fmt)

{

unsigned char R;

switch (fmt) {

case V4L2_PIX_FMT_RGB32:

case V4L2_PIX_FMT_BGR32:

case V4L2_PIX_FMT_RGB24:

R = *(src);

break;

case V4L2_PIX_FMT_RGB565:

R = (*(src) & 0x1F) << 3;

break;

case V4L2_PIX_FMT_SBGGR8:

case V4L2_PIX_FMT_SGBRG8:

case V4L2_PIX_FMT_SGRBG8:

case V4L2_PIX_FMT_YUV420:

case V4L2_PIX_FMT_YUV444:

default:

R = 0;

break;

}

return R;

}

static unsigned char get_G(unsigned char *src, unsigned int fmt)

{

unsigned char G;

switch (fmt) {

case V4L2_PIX_FMT_RGB32:

case V4L2_PIX_FMT_BGR32:

case V4L2_PIX_FMT_RGB24:

G = *(src + 1);

break;

case V4L2_PIX_FMT_RGB565:

G = ((*(src) & 0xE0) >> 3) | ((*(src + 1) & 0x07) << 5);

break;

case V4L2_PIX_FMT_SBGGR8:

case V4L2_PIX_FMT_SGBRG8:

case V4L2_PIX_FMT_SGRBG8:

case V4L2_PIX_FMT_YUV420:

case V4L2_PIX_FMT_YUV444:

default:

G = 0;

break;

}

return G;

}

static unsigned char get_B(unsigned char *src, unsigned int fmt)

{

unsigned char B;

switch (fmt) {

case V4L2_PIX_FMT_RGB32:

case V4L2_PIX_FMT_BGR32:

case V4L2_PIX_FMT_RGB24:

B = *(src + 2);

break;

case V4L2_PIX_FMT_RGB565:

B = (*(src + 1) & 0xF8);

break;

case V4L2_PIX_FMT_SBGGR8:

case V4L2_PIX_FMT_SGBRG8:

case V4L2_PIX_FMT_SGRBG8:

case V4L2_PIX_FMT_YUV420:

case V4L2_PIX_FMT_YUV444:

default:

B = 0;

break;

}

return B;

}

rgb2yuv(char *rgb, char *yuv)

{

int i, j;

unsigned char R, G, B, *y, *u, *v, *alpha;

double RR, GG, BB;

unsigned char *src, *dest;

for (i = 0; i < g_in_height; i++) {

for (j = 0; j < g_in_width; j++) {

src = rgb + (i * g_in_width + j) * get_bpp(g_src_fmt) / 8;

dest = yuv + (i * g_in_width + j) * get_bpp(g_dest_fmt) / 8;

R = get_R(src, g_src_fmt);

G = get_G(src, g_src_fmt);

B = get_B(src, g_src_fmt);

/* normalize to 16 ..235 */

RR = 219 * R / 255 + 16;

GG = 219 * G / 255 + 16;

BB = 219 * B / 255 + 16;

y = dest;

u = dest + 1;

v = dest + 2;

//alpha = dest + 3;

*y = (unsigned char)(0.2991*RR + 0.5849*GG + 0.1159*BB + 0.5);

*u = (unsigned char)(-0.1725*RR - 0.3372*GG + 0.5097*BB + 128.5);

*v = (unsigned char)(0.5097*RR - 0.4254*GG - 0.0843*BB + 128.5);

//*alpha = 255;

}

}

}

int process_cmdline(int argc, char **argv)

{

int i;

char *tmp;

for (i = 1; i < argc; i++) {

if (strcmp(argv[i], "-s") == 0) {

g_src_file = argv[++i];

}

else if (strcmp(argv[i], "-d") == 0) {

g_dest_file = strdup(argv[++i]);

}

else if (strcmp(argv[i], "-sf") == 0) {

tmp = argv[++i];

if (strlen(tmp) == 4) {

g_src_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);

}

}

else if (strcmp(argv[i], "-df") == 0) {

tmp = argv[++i];

if (strlen(tmp) == 4) {

g_dest_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);

}

}

else if (strcmp(argv[i], "iw") == 0) {

g_in_width = atoi(argv[++i]);

}

else if (strcmp(argv[i], "ih") == 0) {

g_in_height = atoi(argv[++i]);

}

}

if (g_src_file && g_dest_file == NULL) {

g_dest_file = malloc(256);

sprintf(g_dest_file, "%s.out", g_src_file);

}

if (g_in_width == 0 || g_in_height == 0) {

}

}

int get_bpp(unsigned int fmt)

{

int ret;

switch (fmt) {

case V4L2_PIX_FMT_RGB32:

case V4L2_PIX_FMT_BGR32:

ret = 32;

break;

case V4L2_PIX_FMT_RGB24:

ret = 24;

break;

case V4L2_PIX_FMT_RGB565:

ret = 16;

break;

case V4L2_PIX_FMT_SBGGR8:

case V4L2_PIX_FMT_SGBRG8:

case V4L2_PIX_FMT_SGRBG8:

ret = 8;

break;

case V4L2_PIX_FMT_YUV420:

ret = 12;

break;

case V4L2_PIX_FMT_YUYV:

case V4L2_PIX_FMT_UYVY:

ret = 16;

break;

case V4L2_PIX_FMT_YUV444:

ret = 24;

break;

default:

ret = -1;

break;

}

return ret;

}

main(int argc, char *argv[])

{

int ret;

int src_fd, dest_fd;

int src_size, dest_size;

char *src_buf;

char *dest_buf;

process_cmdline(argc, argv);

if (g_src_file == NULL || g_dest_file == NULL) {

ret = -1;

goto bailout;

}

src_fd = open(g_src_file, O_RDONLY);

if (src_fd == -1) {

ret = -2;

goto bailout;

}

dest_fd = open(g_dest_file, O_RDWR | O_CREAT, 0666);

if (dest_fd == -1) {

ret = -3;

goto bailout;

}

src_size = g_in_width * g_in_height * get_bpp(g_src_fmt) / 8;

dest_size = g_in_width * g_in_height * get_bpp(g_dest_fmt) / 8;

src_buf = malloc(src_size);

dest_buf = malloc(dest_size);

ret = read(src_fd, src_buf, src_size);

if (ret != src_size) {

printf("src_size=%d, ret=%d\n", src_size, ret);

ret = -4;

goto bailout;

}

rgb2yuv(src_buf, dest_buf);

printf("write out file, size=%d\n", dest_size);

ret = write(dest_fd, dest_buf, dest_size);

if (ret != dest_size) {

ret = -5;

goto bailout;

}

bailout:

printf("ret(%d)\n", ret);

return ret;

}

##################################################################################
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: