因为我的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 <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
##################################################################################
- #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
##################################################################################
- #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 <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;
- }
##################################################################################