Linux设备驱动之LCD显示摄像图像之三进行转换

因为LCD为RGB模式,所以我们所要做的工作就是将我们其他像素模式转换为RGB模式
大部分函数参照/* luvcview */这个应用函数

Convert_manager.c:

#include <config.h>
#include <convert_manager.h>
#include <string.h>

static PT_VideoConvert g_ptVideoConvertHead = NULL;


int RegisterVideoConvert(PT_VideoConvert ptVideoConvert)
{
    PT_VideoConvert ptTmp;

    if (!g_ptVideoConvertHead)
    {
        g_ptVideoConvertHead   = ptVideoConvert;
        ptVideoConvert->ptNext = NULL;
    }
    else
    {
        ptTmp = g_ptVideoConvertHead;
        while (ptTmp->ptNext)
        {
            ptTmp = ptTmp->ptNext;
        }
        ptTmp->ptNext     = ptVideoConvert;
        ptVideoConvert->ptNext = NULL;
    }

    return 0;
}



void ShowVideoConvert(void)
{
    int i = 0;
    PT_VideoConvert ptTmp = g_ptVideoConvertHead;

    while (ptTmp)
    {
        printf("%02d %s\n", i++, ptTmp->name);
        ptTmp = ptTmp->ptNext;
    }
}


PT_VideoConvert GetVideoConvert(char *pcName)
{
    PT_VideoConvert ptTmp = g_ptVideoConvertHead;

    while (ptTmp)
    {
        if (strcmp(ptTmp->name, pcName) == 0)
        {
            return ptTmp;
        }
        ptTmp = ptTmp->ptNext;
    }
    return NULL;
}

PT_VideoConvert GetVideoConvertForFormats(int iPixelFormatIn, int iPixelFormatOut)
{
    PT_VideoConvert ptTmp = g_ptVideoConvertHead;

    while (ptTmp)
    {
        if (ptTmp->isSupport(iPixelFormatIn, iPixelFormatOut))
        {
            return ptTmp;
        }
        ptTmp = ptTmp->ptNext;
    }
    return NULL;
}


int VideoConvertInit(void)
{
    int iError;

    iError = Yuv2RgbInit();
    iError |= Mjpeg2RgbInit();
    iError |= Rgb2RgbInit();

    return iError;
}

mjpeg2rgb:

/* MJPEG : 实质上每一帧数据都是一个完整的JPEG文件 */

#include <convert_manager.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <jpeglib.h>

typedef struct MyErrorMgr
{
    struct jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
}T_MyErrorMgr, *PT_MyErrorMgr;

extern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long);

static int isSupportMjpeg2Rgb(int iPixelFormatIn, int iPixelFormatOut)
{
    if (iPixelFormatIn != V4L2_PIX_FMT_MJPEG)
        return 0;
    if ((iPixelFormatOut != V4L2_PIX_FMT_RGB565) && (iPixelFormatOut != V4L2_PIX_FMT_RGB32))
    {
        return 0;
    }
    return 1;
}



static void MyErrorExit(j_common_ptr ptCInfo)
{
    static char errStr[JMSG_LENGTH_MAX];

    PT_MyErrorMgr ptMyErr = (PT_MyErrorMgr)ptCInfo->err;

    /* Create the message */
    (*ptCInfo->err->format_message) (ptCInfo, errStr);
    DBG_PRINTF("%s\n", errStr);

    longjmp(ptMyErr->setjmp_buffer, 1);
}


//Garmen:转换一行
static int CovertOneLine(int iWidth, int iSrcBpp, int iDstBpp, unsigned char *pudSrcDatas, unsigned char *pudDstDatas)
{
    unsigned int dwRed;
    unsigned int dwGreen;
    unsigned int dwBlue;
    unsigned int dwColor;

    unsigned short *pwDstDatas16bpp = (unsigned short *)pudDstDatas;
    unsigned int   *pwDstDatas32bpp = (unsigned int *)pudDstDatas;

    int i;
    int pos = 0;

    if (iSrcBpp != 24)
    {
        return -1;
    }

    if (iDstBpp == 24)
    {
        memcpy(pudDstDatas, pudSrcDatas, iWidth*3);
    }
    else
    {
        for (i = 0; i < iWidth; i++)
        {
            dwRed   = pudSrcDatas[pos++];
            dwGreen = pudSrcDatas[pos++];
            dwBlue  = pudSrcDatas[pos++];
            if (iDstBpp == 32)
            {
                dwColor = (dwRed << 16) | (dwGreen << 8) | dwBlue;
                *pwDstDatas32bpp = dwColor;
                pwDstDatas32bpp++;
            }
            else if (iDstBpp == 16)
            {
                /* 565 */
                dwRed   = dwRed >> 3;
                dwGreen = dwGreen >> 2;
                dwBlue  = dwBlue >> 3;
                dwColor = (dwRed << 11) | (dwGreen << 5) | (dwBlue);
                *pwDstDatas16bpp = dwColor;
                pwDstDatas16bpp++;
            }
        }
    }
    return 0;
}


//static int GetPixelDatasFrmJPG(PT_FileMap ptFileMap, PT_PixelDatas ptPixelDatas)
/* 把内存里的JPEG图像转换为RGB图像 */
static int Mjpeg2RgbConvert(PT_VideoBuf ptVideoBufIn, PT_VideoBuf ptVideoBufOut)
{
    struct jpeg_decompress_struct tDInfo;
    //struct jpeg_error_mgr tJErr;
    int iRet;
    int iRowStride;
    unsigned char *aucLineBuffer = NULL;
    unsigned char *pucDest;
    T_MyErrorMgr tJerr;

    //Garmen:定义一个PT_PixelDatas类型结构体,等于&ptVideoBufOut->tPixelDatas
    PT_PixelDatas ptPixelDatas = &ptVideoBufOut->tPixelDatas;

    // 分配和初始化一个decompression结构体
    //tDInfo.err = jpeg_std_error(&tJErr);

    tDInfo.err               = jpeg_std_error(&tJerr.pub);
    tJerr.pub.error_exit     = MyErrorExit;

    if(setjmp(tJerr.setjmp_buffer))
    {
        /* 如果程序能运行到这里, 表示JPEG解码出错 */
        jpeg_destroy_decompress(&tDInfo);
        if (aucLineBuffer)
        {
            free(aucLineBuffer);
        }
        if (ptPixelDatas->aucPixelDatas)
        {
            free(ptPixelDatas->aucPixelDatas);
        }
        return -1;
    }

    jpeg_create_decompress(&tDInfo);

    // 用jpeg_read_header获得jpg信息
    //jpeg_stdio_src(&tDInfo, ptFileMap->tFp);
    /* 把数据设为内存中的数据 */
    jpeg_mem_src_tj (&tDInfo, ptVideoBufIn->tPixelDatas.aucPixelDatas, ptVideoBufIn->tPixelDatas.iTotalBytes);


    iRet = jpeg_read_header(&tDInfo, TRUE);

    // 设置解压参数,比如放大、缩小
    tDInfo.scale_num = tDInfo.scale_denom = 1;

    // 启动解压:jpeg_start_decompress   
    jpeg_start_decompress(&tDInfo);

    // 一行的数据长度
    iRowStride = tDInfo.output_width * tDInfo.output_components;
    aucLineBuffer = malloc(iRowStride);

    if (NULL == aucLineBuffer)
    {
        return -1;
    }

    ptPixelDatas->iWidth  = tDInfo.output_width;
    ptPixelDatas->iHeight = tDInfo.output_height;
    //ptPixelDatas->iBpp    = iBpp;
    ptPixelDatas->iLineBytes    = ptPixelDatas->iWidth * ptPixelDatas->iBpp / 8;
    ptPixelDatas->iTotalBytes   = ptPixelDatas->iHeight * ptPixelDatas->iLineBytes;
    if (NULL == ptPixelDatas->aucPixelDatas)
    {
        ptPixelDatas->aucPixelDatas = malloc(ptPixelDatas->iTotalBytes);
    }

    pucDest = ptPixelDatas->aucPixelDatas;

    // 循环调用jpeg_read_scanlines来一行一行地获得解压的数据
    while (tDInfo.output_scanline < tDInfo.output_height)
    {
        /* 得到一行数据,里面的颜色格式为0xRR, 0xGG, 0xBB */
        (void) jpeg_read_scanlines(&tDInfo, &aucLineBuffer, 1);

        // 转到ptPixelDatas去
        CovertOneLine(ptPixelDatas->iWidth, 24, ptPixelDatas->iBpp, aucLineBuffer, pucDest);
        pucDest += ptPixelDatas->iLineBytes;
    }

    free(aucLineBuffer);
    jpeg_finish_decompress(&tDInfo);
    jpeg_destroy_decompress(&tDInfo);

    return 0;
}



static int Mjpeg2RgbConvertExit(PT_VideoBuf ptVideoBufOut)
{
    if (ptVideoBufOut->tPixelDatas.aucPixelDatas)
    {
        free(ptVideoBufOut->tPixelDatas.aucPixelDatas);
        ptVideoBufOut->tPixelDatas.aucPixelDatas = NULL;
    }
    return 0;
}

/* 构造 */
static T_VideoConvert g_tMjpeg2RgbConvert = {
    .name        = "mjpeg2rgb",
    .isSupport   = isSupportMjpeg2Rgb,
    .Convert     = Mjpeg2RgbConvert,
    .ConvertExit = Mjpeg2RgbConvertExit,
};


/* 注册 */
int Mjpeg2RgbInit(void)
{
    return RegisterVideoConvert(&g_tMjpeg2RgbConvert);
}


rgb2rgb:

#include <convert_manager.h>
#include <stdlib.h>
#include <string.h>

static int isSupportRgb2Rgb(int iPixelFormatIn, int iPixelFormatOut)
{
    if (iPixelFormatIn != V4L2_PIX_FMT_RGB565)
        return 0;
    if ((iPixelFormatOut != V4L2_PIX_FMT_RGB565) && (iPixelFormatOut != V4L2_PIX_FMT_RGB32))
    {
        return 0;
    }
    return 1;
}

static int Rgb2RgbConvert(PT_VideoBuf ptVideoBufIn, PT_VideoBuf ptVideoBufOut)
{   
    PT_PixelDatas ptPixelDatasIn  = &ptVideoBufIn->tPixelDatas;
    PT_PixelDatas ptPixelDatasOut = &ptVideoBufOut->tPixelDatas;

    int x, y;
    int r, g, b;
    int color;
    unsigned short *pwSrc = (unsigned short *)ptPixelDatasIn->aucPixelDatas;
    unsigned int *pdwDest;

    if (ptVideoBufIn->iPixelFormat != V4L2_PIX_FMT_RGB565)
    {
        return -1;
    }

    if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB565)
    {
        ptPixelDatasOut->iWidth  = ptPixelDatasIn->iWidth;
        ptPixelDatasOut->iHeight = ptPixelDatasIn->iHeight;
        ptPixelDatasOut->iBpp    = 16;
        ptPixelDatasOut->iLineBytes  = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8;
        ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight;
        if (!ptPixelDatasOut->aucPixelDatas)
        {
            ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes);
        }

        memcpy(ptPixelDatasOut->aucPixelDatas, ptPixelDatasIn->aucPixelDatas, ptPixelDatasOut->iTotalBytes);
        return 0;
    }
    else if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB32)
    {
        ptPixelDatasOut->iWidth  = ptPixelDatasIn->iWidth;
        ptPixelDatasOut->iHeight = ptPixelDatasIn->iHeight;
        ptPixelDatasOut->iBpp    = 32;
        ptPixelDatasOut->iLineBytes  = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8;
        ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight;
        if (!ptPixelDatasOut->aucPixelDatas)
        {
            ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes);
        }

        pdwDest = (unsigned int *)ptPixelDatasOut->aucPixelDatas;

        for (y = 0; y < ptPixelDatasOut->iHeight; y++)
        {
            for (x = 0; x < ptPixelDatasOut->iWidth; x++)
            {
                color = *pwSrc++;
                /* 从RGB565格式的数据中提取出R,G,B */
                r = color >> 11;
                g = (color >> 5) & (0x3f);
                b = color & 0x1f;

                /* 把r,g,b转为0x00RRGGBB的32位数据 */
                color = ((r << 3) << 16) | ((g << 2) << 8) | (b << 3);

                *pdwDest = color;
                pdwDest++;
            }
        }
        return 0;
    }

    return -1;
}

static int Rgb2RgbConvertExit(PT_VideoBuf ptVideoBufOut)
{
    if (ptVideoBufOut->tPixelDatas.aucPixelDatas)
    {
        free(ptVideoBufOut->tPixelDatas.aucPixelDatas);
        ptVideoBufOut->tPixelDatas.aucPixelDatas = NULL;
    }
    return 0;
}

/* 构造 */
static T_VideoConvert g_tRgb2RgbConvert = {
    .name        = "rgb2rgb",
    .isSupport   = isSupportRgb2Rgb,
    .Convert     = Rgb2RgbConvert,
    .ConvertExit = Rgb2RgbConvertExit,
};


/* 注册 */
int Rgb2RgbInit(void)
{
    return RegisterVideoConvert(&g_tRgb2RgbConvert);
}

yuv2rgb:

#include <convert_manager.h>
#include <stdlib.h>
#include "color.h"

static int isSupportYuv2Rgb(int iPixelFormatIn, int iPixelFormatOut)
{
    if (iPixelFormatIn != V4L2_PIX_FMT_YUYV)
        return 0;
    if ((iPixelFormatOut != V4L2_PIX_FMT_RGB565) && (iPixelFormatOut != V4L2_PIX_FMT_RGB32))
    {
        return 0;
    }
    return 1;
}



/* translate YUV422Packed to rgb24 */

static unsigned int
Pyuv422torgb565(unsigned char * input_ptr, unsigned char * output_ptr, unsigned int image_width, unsigned int image_height)
{
    unsigned int i, size;
    unsigned char Y, Y1, U, V;
    unsigned char *buff = input_ptr;
    unsigned char *output_pt = output_ptr;

    unsigned int r, g, b;
    unsigned int color;

    size = image_width * image_height /2;
    for (i = size; i > 0; i--) {
        /* bgr instead rgb ?? */
        Y = buff[0] ;
        U = buff[1] ;
        Y1 = buff[2];
        V = buff[3];
        buff += 4;
        r = R_FROMYV(Y,V);
        g = G_FROMYUV(Y,U,V); //b
        b = B_FROMYU(Y,U); //v

        /* 把r,g,b三色构造为rgb565的16位值 */
        r = r >> 3;
        g = g >> 2;
        b = b >> 3;
        color = (r << 11) | (g << 5) | b;
        *output_pt++ = color & 0xff;
        *output_pt++ = (color >> 8) & 0xff;

        r = R_FROMYV(Y1,V);
        g = G_FROMYUV(Y1,U,V); //b
        b = B_FROMYU(Y1,U); //v

        /* 把r,g,b三色构造为rgb565的16位值 */
        r = r >> 3;
        g = g >> 2;
        b = b >> 3;
        color = (r << 11) | (g << 5) | b;
        *output_pt++ = color & 0xff;
        *output_pt++ = (color >> 8) & 0xff;
    }

    return 0;
}




/* translate YUV422Packed to rgb24 */

static unsigned int
Pyuv422torgb32(unsigned char * input_ptr, unsigned char * output_ptr, unsigned int image_width, unsigned int image_height)
{
    unsigned int i, size;
    unsigned char Y, Y1, U, V;
    unsigned char *buff = input_ptr;
    unsigned int *output_pt = (unsigned int *)output_ptr;

    unsigned int r, g, b;
    unsigned int color;

    size = image_width * image_height /2;
    for (i = size; i > 0; i--) {
        /* bgr instead rgb ?? */
        Y = buff[0] ;
        U = buff[1] ;
        Y1 = buff[2];
        V = buff[3];
        buff += 4;

        r = R_FROMYV(Y,V);
        g = G_FROMYUV(Y,U,V); //b
        b = B_FROMYU(Y,U); //v
        /* rgb888 */
        color = (r << 16) | (g << 8) | b;
        *output_pt++ = color;

        r = R_FROMYV(Y1,V);
        g = G_FROMYUV(Y1,U,V); //b
        b = B_FROMYU(Y1,U); //v
        color = (r << 16) | (g << 8) | b;
        *output_pt++ = color;
    }

    return 0;
}

/* 参考luvcview */
static int Yuv2RgbConvert(PT_VideoBuf ptVideoBufIn, PT_VideoBuf ptVideoBufOut)
{
    PT_PixelDatas ptPixelDatasIn  = &ptVideoBufIn->tPixelDatas;
    PT_PixelDatas ptPixelDatasOut = &ptVideoBufOut->tPixelDatas;

    ptPixelDatasOut->iWidth  = ptPixelDatasIn->iWidth;
    ptPixelDatasOut->iHeight = ptPixelDatasIn->iHeight;

    if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB565)
    {
        ptPixelDatasOut->iBpp = 16;
        ptPixelDatasOut->iLineBytes  = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8;
        ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight;

        if (!ptPixelDatasOut->aucPixelDatas)
        {
            ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes);
        }

        Pyuv422torgb565(ptPixelDatasIn->aucPixelDatas, ptPixelDatasOut->aucPixelDatas, ptPixelDatasOut->iWidth, ptPixelDatasOut->iHeight);
        return 0;
    }
    else if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB32)
    {
        ptPixelDatasOut->iBpp = 32;
        ptPixelDatasOut->iLineBytes  = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8;
        ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight;

        if (!ptPixelDatasOut->aucPixelDatas)
        {
            ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes);
        }

        Pyuv422torgb32(ptPixelDatasIn->aucPixelDatas, ptPixelDatasOut->aucPixelDatas, ptPixelDatasOut->iWidth, ptPixelDatasOut->iHeight);
        return 0;
    }

    return -1;
}

static int Yuv2RgbConvertExit(PT_VideoBuf ptVideoBufOut)
{
    if (ptVideoBufOut->tPixelDatas.aucPixelDatas)
    {
        free(ptVideoBufOut->tPixelDatas.aucPixelDatas);
        ptVideoBufOut->tPixelDatas.aucPixelDatas = NULL;
    }
    return 0;
}

/* 构造 */
static T_VideoConvert g_tYuv2RgbConvert = {
    .name        = "yuv2rgb",
    .isSupport   = isSupportYuv2Rgb,
    .Convert     = Yuv2RgbConvert,
    .ConvertExit = Yuv2RgbConvertExit,
};

extern void initLut(void);

/* 注册 */
int Yuv2RgbInit(void)
{
    initLut();
    return RegisterVideoConvert(&g_tYuv2RgbConvert);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值