视频图像数据处理七:将rgb视频图像封装为bmp图像


本文介绍了将rgb视频图像封装为bmp图像的方法,附有详细的代码和图像示例。文中rgb24文件需要使用yuv/rgb播放器才能查看,参考播放器可选择雷神推荐的修改了一个YUV/RGB播放器,或者小编使用的vooya播放器

bmp结构

bmp图片由文件头和像素两部分组成,其中文件头又包括位图文件信息和位图结构信息,文件头两部分信息的结构如下所示。

typedef  struct  tagBITMAPFILEHEADER
{
	unsigned short int  bfType;       //位图文件的类型,必须为BM 
	unsigned long       bfSize;       //文件大小,以字节为单位
	unsigned short int  bfReserverd1; //位图文件保留字,必须为0 
	unsigned short int  bfReserverd2; //位图文件保留字,必须为0 
	unsigned long       bfbfOffBits;  //位图文件头到数据的偏移量,以字节为单位
}BITMAPFILEHEADER;
typedef  struct  tagBITMAPINFOHEADER
{
	long biSize;                        //该结构大小,字节为单位
	long  biWidth;                     //图形宽度以象素为单位
	long  biHeight;                     //图形高度以象素为单位
	short int  biPlanes;               //目标设备的级别,必须为1 
	short int  biBitcount;             //颜色深度,每个象素所需要的位数
	short int  biCompression;        //位图的压缩类型
	long  biSizeImage;              //位图的大小,以字节为单位
	long  biXPelsPermeter;       //位图水平分辨率,每米像素数
	long  biYPelsPermeter;       //位图垂直分辨率,每米像素数
	long  biClrUsed;            //位图实际使用的颜色表中的颜色数
	long  biClrImportant;       //位图显示过程中重要的颜色数
}BITMAPINFOHEADER;

BMP采用的是小端(Little Endian)存储方式。这种存储方式中“RGB24”格式的像素的分量存储的先后顺序为B、G、R。由于RGB24格式存储的顺序是R、G、B,所以需要将“R”和“B”顺序作一个调换再进行存储。

函数代码

本函数实现了将rgb视频图像封装为bmp图像,具体代码如下所示。

int CTransPic::simplest_rgb24_to_bmp(const char*url, int w, int h, const char* bmppath)
{
	typedef struct
	{
		long imageSize;
		long black;
		long startposion;
	}BmpHead;
	typedef struct
	{
		long  Length;
		long  width;
		long  height;
		unsigned short  colorPlane;
		unsigned short  bitColor;
		long  zipFormat;
		long  realSize;
		long  xPels;
		long  yPels;
		long  colorUse;
		long  colorImportant;
	}InfoHead;
	BmpHead m_BmpHeader = { 0 };
	InfoHead m_BmpInfoHeader = { 0 };
	char bfType[2] = { 'B', 'M' };
	int Head_Size = sizeof(InfoHead)+sizeof(BmpHead)+sizeof(bfType);
	unsigned char* rgb24_buffer = NULL;
	fstream fp_rgb24, fp_bmp;
	fp_rgb24.open(url, ios::in | ios::binary);
	fp_bmp.open(bmppath, ios::out | ios::binary);

	rgb24_buffer = (unsigned char*)malloc(w*h * 3);
	fp_rgb24.read((char*)rgb24_buffer, w*h * 3);
	m_BmpHeader.imageSize = 3 * w*h + Head_Size;
	m_BmpHeader.startposion = Head_Size;

	m_BmpInfoHeader.Length = sizeof(InfoHead);
	m_BmpInfoHeader.width = w;
	//BMP storage pixel data in opposite direction of Y-axis (from bottom to top).
	m_BmpInfoHeader.height = -h;
	m_BmpInfoHeader.colorPlane = 1;
	m_BmpInfoHeader.bitColor = 24;
	m_BmpInfoHeader.realSize = 3 * w*h;
	fp_bmp.write(bfType, sizeof(bfType));
	fp_bmp.write((const char*)&m_BmpHeader, sizeof(m_BmpHeader));
	fp_bmp.write((const char*)&m_BmpInfoHeader, sizeof(m_BmpInfoHeader));

	//BMP save R1|G1|B1,R2|G2|B2 as B1|G1|R1,B2|G2|R2
	//It saves pixel data in Little Endian
	//So we change 'R' and 'B'
	for (int j = 0; j < h; j++){
		for (int i = 0; i < w; i++){
			char temp = rgb24_buffer[(j*w + i) * 3 + 2];
			rgb24_buffer[(j*w + i) * 3 + 2] = rgb24_buffer[(j*w + i) * 3 + 0];
			rgb24_buffer[(j*w + i) * 3 + 0] = temp;
		}
	}
	fp_bmp.write((const char*)rgb24_buffer, w*h * 3);
	free(rgb24_buffer);
	fp_bmp.close();
	fp_rgb24.close();

	return 0;
}

函数调用方法如下所示。

TranPic.simplest_rgb24_to_bmp("2_1000x667.rgb", 1000, 667, "output_bmp.bmp");

测试用例

程序测试用的原图如下所示:
2_1000x667_rgb

2_1000x667.rgb

测试输出bmp图像如下所示。
2_1000x667_rgb.bmp

2_1000x667_rgb.bmp

下载

vooya播放器:https://download.csdn.net/download/whegqing/11519824
测试用例图:https://download.csdn.net/download/whegqing/11520875


版本声明:本文参考了雷神的文章,文中代码重新做了编写,亲测可用,欢迎转载交

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

i胡说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值