因为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);
}