织梦CMS - 轻松建站从此开始!

罗索

bayer, yuv, RGB转换方法

落鹤生 发布于 2012-08-27 10:48 点击:次 
因为我的STVxxx USB camera输出格式是bayer格式,手头上只有YUVTOOLS这个查看工具,没法验证STVxxx在开发板上是否正常工作。网上找了很久也没找到格式转换工具,最后放弃了,觉得还是写个转换工具比较快。抄写了部分libv4lconvert的代码, 我只验证了
TAG:

因为我的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)


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

(kickxxx)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201208/16232.html]
本文出处:CSDN博客 作者:kickxxx 原文
顶一下
(4)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容