内存中读取bmp图片转换为IplImage格式

        前些天做一个项目,其中要对读入内存的bmp图片转格式,转换为IplImage格式提供给OpenCV处理。内存中的图片是通过Socket从远程传输过来的。仅提供图片的首地址和长度,编写转换的接口。

        由于bmp图像大多未经压缩,不同于jpeg的复杂压缩算法,直接从内存中读取bmp图片即可完成转换。首先了解bmp文件格式。

       bmp文件由以下部分组成,1、文件信息头,2、bmp信息头,3、调色板(可选),4、图像数据。对于调色板,仅在深度为8时存在(每个像素有256种表示),当今的bmp图像色深普遍为24或32bit,3通道或4通道,因此大多无调色板。存在调色板的图片,其图像数据中每个像素为调色板的索引,因此处理调色板图片时,需要把索引值转换为标准像素值。由于bmp图像大多无调色板,因此该程序没有处理调色板特殊情况,同时也没有处理存在压缩的情况。

在网上找到一个IplImage和bmp相互转换的例子,是基于类对象封装的,但不够简洁,就编写了如下代码。

在工程中首先定义bmp文件头和信息头,注意内存对齐。

//文件头结构体
#pragma pack(push)
#pragma pack(2)  //两字节对齐,否则bmp_fileheader会占16Byte
//bmp文件头
struct bmp_fileheader
{
	unsigned short   bfType; //文件标识
        unsigned long	 bfSize; //文件大小
        unsigned long	 bfReverved1; //保留
  	unsigned long    bfOffBits;//数据偏移
};

//bmp信息头
struct bmp_infoheader
{
	unsigned long    biSize;//信息头长度
 	unsigned long    biWidth;//宽度
	unsigned long    biHeight;//高度
	unsigned short   biPlanes;//柱面数=1
 	unsigned short   biBitCount;//像素位数
	unsigned long    biCompression;//压缩说明
	unsigned long    biSizeImage;//位图数据的大小
	unsigned long    biXPelsPerMeter;//水平分辨率
	unsigned long    biYpelsPerMeter;//垂直分辨率
	unsigned long    biClrUsed;//使用的颜色数
	unsigned long    biClrImportant;//重要的颜色数
};

#pragma pack(pop)
其中部分参照了bmp文件格式说明。

定义基本格式后,就要对内存中的图像进行读取转换,定义如下函数:

IplImage *BMP2Ipl(unsigned char *src, int FileSize)
{ 
	bmp_fileheader *Fileheader = (bmp_fileheader *)src;
	//检查错误
	assert(FileSize == Fileheader->bfSize);
	//判断是否是位图
	if(Fileheader->bfType!= 0x4d42)
		return NULL;
	//开始处理信息头
	bmp_infoheader *bmpheader = (bmp_infoheader *)(src + sizeof(bmp_fileheader));
	unsigned int width = bmpheader->biWidth;//宽度
	unsigned int height = bmpheader->biHeight;//高度
	unsigned int hSize = bmpheader->biSize;//信息头长度

	if(bmpheader->biBitCount < 24)
		return NULL;//支持真色彩32位

	if(bmpheader->biCompression != 0)
		return NULL;//不支持压缩算法

	//数据大小
	unsigned int dataByteSize = bmpheader->biSizeImage;//实际位图数据大小
	unsigned int rowByteSize = dataByteSize/height;//对齐的每行数据

	IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, bmpheader->biBitCount/8);
	//拷贝实际数据无颜色表
	unsigned char *gc = src + FileSize - rowByteSize;
	char *p = img->imageData;
	for(int i=0; i
该函数不支持压缩的图片,由于bmp图像数据是倒置从文件尾部逐行存储,因此转换过程中需要倒置数据。

转换后的IplImage直接拿来用就可以了。

你可能感兴趣的:(图像处理)