因为我的STVxxx USB camera输出格式是bayer格式,手头上只有YUVTOOLS这个查看工具,没法验证STVxxx在开发板上是否正常工作。
网上找了很久也没找到格式转换工具,最后放弃了,觉得还是写个转换工具比较快。抄写了部分libv4lconvert的代码, 我只验证了
V4L2_PIX_FMT_SGBRG8到V4L2_PIX_FMT_YUV420的转换。
bayer.c
##################################################################################
/*
* lib4lconvert, video4linux2 format conversion lib
* (C) 2008 Hans de Goede
*
* 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
#include
#include
#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
##################################################################################
#include
#include
#include
#include
#include
#include
#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
##################################################################################
#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
##################################################################################
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表示。
##################################################################################
#include
#include
#include
#include
#include
#include
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;
}