在windows编程中,很多图片信息,都是基于windows系统所谓的DIB(设备无关位图)的结构,其定义在结构体 BITMAPINFOHEADER 中。
将windows 定义的DIB 结构和Opencv内部定义的IPLImage结构做相互转化。参考代码如下所示。
头文件bmp2ipl.h
#ifndef BMP2IPL_H #define BMP2IPL_H class BMP { public: BMP():bmpData(NULL) { memset(&biHeader, 0, sizeof(biHeader)); } BMP(const BMP & img); BMP(const IplImage &img); BMP(int width, int height, int bitCount); ~BMP(){ delete [] bmpData; } bool CreateImage(const BITMAPINFOHEADER &biHeader); IplImage * BMP2Ipl(); void ReSize(int newW, int newH); private: void CopyData(char *dest, const char *src, int dataByteSize, bool isConvert, int height); // isConvert=true 进行顶左和底左之间的转换(顶左到底左或底左到顶左),否则不转换 // biSizeImage may be set to zero for BI_RGB bitmaps, so calculate it. int ImgSize() { return (biHeader.biHeight*((biHeader.biWidth*biHeader.biBitCount/8+3)&(-4))); } public: void Clear(); BITMAPINFOHEADER biHeader; unsigned char * bmpData; }; #endif实现文件bmp2ipl.cpp
#include "bmp2ipl.h" BMP::BMP(const BMP & img){ if(!IsSupport(img)) { BMP(); return; } //biHeader = img.biHeader; PBITMAPINFOHEADER pBmpH = (PBITMAPINFOHEADER)&img.biHeader; memcpy(&biHeader, pBmpH, sizeof(BITMAPINFOHEADER)); biHeader.biSizeImage = ImgSize(); bool isLowerLeft = biHeader.biHeight>0; //int rowSize=0; if(!isLowerLeft) biHeader.biHeight=-biHeader.biHeight; if(bmpData!=NULL) delete[] bmpData; bmpData = new unsigned char [biHeader.biSizeImage]; //memcpy(bmpData, img.bmpData, img.biHeader.biSizeImage); CopyData((char *)bmpData, (char*)img.bmpData, biHeader.biSizeImage, !isLowerLeft, biHeader.biHeight); } BMP::BMP(const IplImage &img) { if(!IsSupport(img)) { BMP(); return; } bool isTopLeft = (img.origin == IPL_ORIGIN_TL); biHeader.biSize = sizeof(BITMAPINFOHEADER); biHeader.biWidth = img.width; biHeader.biHeight = img.height; biHeader.biPlanes = 1; biHeader.biBitCount = img.depth * img.nChannels; biHeader.biCompression = BI_RGB; biHeader.biSizeImage = img.imageSize; biHeader.biXPelsPerMeter = 0; biHeader.biYPelsPerMeter = 0; biHeader.biClrUsed = 0; biHeader.biClrImportant = 0; if(bmpData!=NULL) delete[] bmpData; bmpData = new unsigned char [img.imageSize]; //memcpy(bmpData, img.ImageData, img.imageSize); CopyData((char*)bmpData, (char*)img.imageData, img.imageSize, isTopLeft, img.height); } BMP::BMP(int width, int height, int bitCount) { if(bitCount!=8 && bitCount!=24) return; biHeader.biSize = sizeof(BITMAPINFOHEADER); biHeader.biWidth = width; biHeader.biHeight = height; biHeader.biPlanes = 1; biHeader.biBitCount = bitCount; biHeader.biCompression = BI_RGB; biHeader.biSizeImage = ImgSize(); biHeader.biXPelsPerMeter = 0; biHeader.biYPelsPerMeter = 0; biHeader.biClrUsed = 0; biHeader.biClrImportant = 0; if(bmpData!=NULL) delete[] bmpData; bmpData = new unsigned char [biHeader.biSizeImage]; Clear(); } void BMP::CopyData(char *dest, const char *src, int dataByteSize, bool isConvert, int height) { char * p = dest; if(!isConvert) { memcpy(dest, src, dataByteSize); return; } if(height<=0) return; int rowByteSize = dataByteSize / height; src = src + dataByteSize - rowByteSize ; for(int i=0; i<height; i++) { memcpy(dest, src, rowByteSize); dest += rowByteSize; src -= rowByteSize; } } IplImage * BMP::BMP2Ipl() { if(!IsSupport(*this)) return NULL; IplImage *iplImg; int height; bool isLowerLeft = biHeader.biHeight>0; height = (biHeader.biHeight>0) ? biHeader.biHeight : -biHeader.biHeight; iplImg = cvCreateImage(cvSize(biHeader.biWidth,height),IPL_DEPTH_8U,biHeader.biBitCount/8); CopyData( iplImg->imageData, (char*)bmpData, biHeader.biSizeImage, isLowerLeft, height); return iplImg; } void BMP::Clear() { if(bmpData == NULL) return; memset(bmpData, 0, ImgSize()); } void BMP::ReSize(int newW, int newH) { biHeader.biWidth = newW; biHeader.biHeight = newH; biHeader.biSizeImage = ImgSize(); if(bmpData!=NULL) delete[] bmpData; bmpData = new unsigned char [biHeader.biSizeImage]; Clear(); } bool BMP::CreateImage(const BITMAPINFOHEADER &bih) { memset(&biHeader,0,sizeof(BITMAPINFOHEADER)); delete[] bmpData; bmpData = NULL; memcpy(&biHeader, &bih, sizeof(BITMAPINFOHEADER)); biHeader.biSizeImage = ImgSize(); bmpData = new unsigned char [ biHeader.biSizeImage ]; if(bmpData == NULL) return false; else{ Clear(); return true; } }