C语言实现BMP格式转RGB格式YUV格式
Posted 代二毛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言实现BMP格式转RGB格式YUV格式相关的知识,希望对你有一定的参考价值。
前言
此代码的功能是传入BMP格式的数据,传出提取的RGB数据。BMP图像支持8bit、16bit、24bit、32bit的格式,得到的都是24bit的RGB格式图像,如果想得到YUV格式的图像,可以将得到RGB再转为YUV格式。RGB转YUV格式参考博客《C语言实现RGB packet格式转YUV(NV21)格式》。
代码
//BMP图片的压缩方式
#define BI_RGB (0)
#define BI_BITFIELDS (3)
//RGB555的掩码
#define RGB555_RED_MASK (31744)
#define RGB555_GREEN_MASK (992)
#define RGB555_BLUE_MASK (31)
//RGB565的掩码
#define RGB565_RED_MASK (63488)
#define RGB565_GREEN_MASK (2016)
#define RGB565_BLUE_MASK (31)
//BMP图片的像素位数
#define BMP_8_BIT (8)
#define BMP_16_BIT (16)
#define BMP_24_BIT (24)
#define BMP_32_BIT (32)
//16位BMP图片从文件头到图像数据的偏移量
#define BMP_16_BIT_BI_BITFIELDS_OFFSET (66)
#define BMP_16_BIT_BI_RGB_OFFSET (54)
//8位BMP图片调色板的大小
#define BMP_8_BIT_OFFSET (1024)
//BMP图片的文件头,固定14字节
#define BMP_FILE_HEADER_LENGTH (14)
# isNull(ptr) (NULL == (ptr))
# isNotNull(ptr) (NULL != (ptr))
//BMP图片的信息头
typedef struct InfoHeader
{
Uint32 bisize;//信息头的大小,一般是40
Int32 biWidth;//位图的宽
Int32 biHeight;//位图的高
Uint16 biPlanes;//固定值1
Uint16 biBitCount;//每个像素的位数
Uint32 biCompression;//压缩方式,BI_RGB(0)为不压缩, BI_BITFIELDS(3)用于16位、32位位图
Uint32 biSizeImage;//位图全部像素占用的字节
Int32 biXpelsPerMeter;//水平分辨率
Int32 biYPelsPerMeter;//垂直分辨率
Uint32 biClrUsed;//位图使用的颜色数。0代表颜色数为2的biBitCount次方
Uint32 biClrImportant;//重要的颜色数,0代表所有颜色都重要
}BmpInfoHeader;
Int32 BMPExtractBGR(Uint8* pSrcData, Uint8* pDstData)
{
BmpInfoHeader BmpInfoHeader;
Uint32 width, height;
Int32 i, j;
Int32 offSet;
Int32 RGB24 = 0;
Uint16 RGB16 = 0;
Int32 count = 0;
if(isNull(pSrcData) || isNull(pDstData))
{
printf("input parameter invalid\\n");
return -1;
}
//获取信息头
memcpy(&BmpInfoHeader, pSrcData + BMP_FILE_HEADER_LENGTH, sizeof(IVS_BmpInfoHeader));
width = BmpInfoHeader.biWidth;
height = BmpInfoHeader.biHeight;
//判断BMP图片像素的位数
if(BmpInfoHeader.biBitCount == BMP_24_BIT)
{
offSet = BMP_FILE_HEADER_LENGTH + BmpInfoHeader.bisize;//文件头到BGR数据的偏移量
j = 0;
//读取文件的BRG数据
for(i = height - 1; i >=0; i-- )
{
memcpy(pDstData + j * width * 3, pSrcData + offSet + i * width * 3, width * 3);
j++;
}
}
else if(BmpInfoHeader.biBitCount == BMP_8_BIT)
{
offSet = BMP_FILE_HEADER_LENGTH + BmpInfoHeader.bisize + BMP_8_BIT_OFFSET;
for(i = height - 1; i >= 0; i --)
{
for(j = 0; j < width; j++)
{
memcpy(pDstData + count * 3, pSrcData + BMP_FILE_HEADER_LENGTH + BmpInfoHeader.bisize + 4 * (int)pSrcData[offSet + i * width + j], 3);
count++;
}
}
}
else if(BmpInfoHeader.biBitCount == BMP_16_BIT)
{
if(BmpInfoHeader.biCompression == BI_BITFIELDS)
{
//根据掩码判断是RGB555
if((*((Int32 *)(pSrcData + 54)) == RGB555_RED_MASK) && (*((Int32 *)(pSrcData + 58)) == RGB555_GREEN_MASK) \\
&& (*((Int32 *)(pSrcData + 62)) == RGB555_BLUE_MASK))
{
//提取BGR数据
for(i = height - 1; i >= 0; i--)
{
for(j = 0; j < width; j++)
{
RGB24 = 0;
RGB16 = *((Uint16 *)(pSrcData + BMP_16_BIT_BI_BITFIELDS_OFFSET + 2 * (i * width + j)));
RGB24 |= ((RGB16 & RGB555_RED_MASK) << 9) | ((RGB16 & RGB555_GREEN_MASK) << 6) | ((RGB16 & RGB555_BLUE_MASK) << 3);
memcpy(pDstData + count * 3, &RGB24, 3);
count++;
}
}
}
//根据掩码判断是RGB565
else if((*((Int32 *)(pSrcData + 54)) == RGB565_RED_MASK) && (*((Int32 *)(pSrcData + 58)) == RGB565_GREEN_MASK) \\
&& (*((Int32 *)(pSrcData + 62)) == RGB565_BLUE_MASK))
{
for(i = height - 1; i >= 0; i--)
{
for(j = 0; j < width; j++)
{
RGB24 = 0;
RGB16 = *((Uint16 *)(pSrcData + BMP_16_BIT_BI_BITFIELDS_OFFSET + 2 * (i * width + j)));
RGB24 |= ((RGB16 & RGB565_RED_MASK) << 8) | ((RGB16 & RGB565_GREEN_MASK) << 5) | ((RGB16 & RGB565_BLUE_MASK) << 3);
memcpy(pDstData + count * 3, &RGB24, 3);
count++;
}
}
}
}
else if(BmpInfoHeader.biCompression == BI_RGB)
{
//提取BGR数据
for(i = height - 1; i >= 0; i--)
{
for(j = 0; j < width; j++)
{
RGB24 = 0;
RGB16 = *((Uint16 *)(pSrcData + BMP_16_BIT_BI_RGB_OFFSET + 2 * (i * width + j)));
RGB24 |= ((RGB16 & RGB555_RED_MASK) << 9) | ((RGB16 & RGB555_GREEN_MASK) << 6) | ((RGB16 & RGB555_BLUE_MASK) << 3);
memcpy(pDstData + count * 3, &RGB24, 3);
count++;
}
}
}
}
else if(BmpInfoHeader.biBitCount == BMP_32_BIT)
{
offSet = BMP_FILE_HEADER_LENGTH + BmpInfoHeader.bisize;//文件头到BGR数据的偏移量
count = 0;
for(i = height - 1; i >= 0; i--)
{
for(j = 0; j < width; j++)
{
memcpy(pDstData + 3 *count, pSrcData + offSet + 4 *(i * width + j), 3);
count++;
}
}
}
else
{
printf("not support bmp format\\n");
return -1;
}
return 0;
}
以上是关于C语言实现BMP格式转RGB格式YUV格式的主要内容,如果未能解决你的问题,请参考以下文章
PAL或者NTSC制式 BT.656(YUV 4:2:2) 转化为BMP格式图片(RGB)算法