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

来源:互联网 发布:微软sql server官网 编辑:程序博客网 时间:2024/05/16 09:46

        前些天做一个项目,其中要对读入内存的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<height; ++i){ memcpy(p, gc, rowByteSize); p += rowByteSize;          gc -= rowByteSize; }/**/////通道数处理//for(int i=0;i<height;++i)//{//for(int j=0;j<width;++j)//{//*(p+3*j+0) = *(gc+3*j+0);//通道0//*(p+3*j+1) = *(gc+3*j+1);//通道1//*(p+3*j+2) = *(gc+3*j+2);//通道2//}//p += rowByteSize;          //gc -= rowByteSize;//}return img;}    
该函数不支持压缩的图片,由于bmp图像数据是倒置从文件尾部逐行存储,因此转换过程中需要倒置数据。

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

0 0