首先我们要了解两种数据结构 


IplImag 对象结构: 


/************************************************************************************************** 

    *                                                                                                 * 

    *  NOTE:                                                                                          * 

    *    Only use the "8 bit, 1 or 3 channels" image, the BitMap use LowerLeft (底左),              * 

    *    the IplImage use TopLeft (顶左)                                                            * 

    *  IplImage:                                                                                      * 

    *    nChannels = 1 or 3       number of channels                                                  * 

    *    depth = IPL_DEPTH_8U     pixel depth (8 bit), IPL_DEPTH_8U=8                                 * 

    *    dataOrder = 0            交叉存取颜色通道                                                    * 

    *    origin = IPL_ORIGIN_TL   图像数据保存形式,IPL_ORIGIN_BL底左结构, IPL_ORIGIN_TL顶左结构      * 

    *    align = 4                行数据对齐方式,保证下一行数据从整4字节位置开始                     * 

    *    width                                                                                        * 

    *    height                                                                                       * 

    *    widthStep                图像数据行大小,单位字节                                            * 

    *    imageSize                图像数据大小(=height*widthStep),单位字节                           * 

    *    imageData                指向图像数据区,char *                                              * 

    *  BITMAPINFOHEADER:                                                                              * 

    *    biSize                   Specifies the number of bytes required by the structure             * 

    *    biWidth                                                                                      * 

    *    biHeight(>0)             biHeight>0底左结构;biHeight<0顶左结构                              * 

    *    biPlanes = 1             Specifies the number of planes for the target device. This value    * 

    *                             must be set to 1.                                                   * 

    *    biBitCount =8 or 24      bits-per-pixel,8-(pixelDepth=8,channels=1),                         * 

    *                             24-(pixelDepth=8,channels=3)                                        * 

    *    biCompression = BI_RGB   An uncompressed format                                              * 

    *    biSizeImage              Specifies the size, in bytes, of the image.This may be set to zero  * 

    *                             for BI_RGB bitmaps.                                                 * 

    *    biXPelsPerMeter = 0                                                                          * 

    *    biYPelsPerMeter = 0                                                                          * 

    *    biClrUsed = 0                                                                                * 

    *    biClrImportant = 0                                                                           * 

    *                                                                                                 * 

    ***************************************************************************************************/ 


  


BMP文件对象 


1. BMP文件组成 

BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。 

2. BMP文件头 

BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。 


其结构定义如下: 


typedef struct tagBITMAPFILEHEADER 

{ 

WORDbfType; // 位图文件的类型,必须为BM 

DWORD bfSize; // 位图文件的大小,以字节为单位 

WORDbfReserved1; // 位图文件保留字,必须为0 

WORDbfReserved2; // 位图文件保留字,必须为0 

DWORD bfOffBits; // 位图数据的起始位置,以相对于位图 

// 文件头的偏移量表示,以字节为单位 

} BITMAPFILEHEADER; 


3. 位图信息头 


BMP位图信息头数据用于说明位图的尺寸等信息。 

typedef struct tagBITMAPINFOHEADER{ 

DWORD biSize; // 本结构所占用字节数 

LONGbiWidth; // 位图的宽度,以像素为单位 

LONGbiHeight; // 位图的高度,以像素为单位 

WORD biPlanes; // 目标设备的级别,必须为1 

WORD biBitCount// 每个像素所需的位数,必须是1(双色), 

// 4(16色),8(256色)或24(真彩色)之一 

DWORD biCompression; // 位图压缩类型,必须是 0(不压缩), 

// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 

DWORD biSizeImage; // 位图的大小,以字节为单位 

LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数 

LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数 

DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数 

DWORD biClrImportant;// 位图显示过程中重要的颜色数 

} BITMAPINFOHEADER; 


4. 颜色表 

颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: 


typedef struct tagRGBQUAD { 

BYTErgbBlue;// 蓝色的亮度(值范围为0-255) 

BYTErgbGreen; // 绿色的亮度(值范围为0-255) 

BYTErgbRed; // 红色的亮度(值范围为0-255) 

BYTErgbReserved;// 保留,必须为0 

} RGBQUAD; 

颜色表中RGBQUAD结构数据的个数有biBitCount来确定: 

当biBitCount=1,4,8时,分别有2,16,256个表项; 

当biBitCount=24时,没有颜色表项。 

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: 

typedef struct tagBITMAPINFO { 

BITMAPINFOHEADER bmiHeader; // 位图信息头 

RGBQUAD bmiColors[1]; // 颜色表 

} BITMAPINFO; 



5. 位图数据 

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数: 


当biBitCount=1时,8个像素占1个字节; 

当biBitCount=4时,2个像素占1个字节; 

当biBitCount=8时,1个像素占1个字节; 

当biBitCount=24时,1个像素占3个字节; 

Windows规定一个扫描行所占的字节数必须是 

4的倍数(即以long为单位),不足的以0填充, 



接下来实现一个相互转换的类 


//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); 


//Export 

IplImage * BMP2Ipl(); 

//void Show(HWND hWnd, int nID); 

//void Show(CDC *pDC, CRect & rect); 

//void Show(HWND hWnd); 


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 



       


#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); 

/*int i,j; 

CvScalar s; 

for(i=0;i<img.width;i++) 

for(j=0;j<img.height;j++){ 

s=cvGet2D(&img,i,j); 


} 

*/ 

} 


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(); 

} 


// dest: the destination image 

// dataByteSize: the Source image 

// height: source image height 

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 height = dataByteSize/rowByteSize; 

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); 

//iplImg = cvCreateImageHeader( cvSize(biHeader.biWidth, height), IPL_DEPTH_8U, biHeader.biBitCount / 8); 


//cvSetData(iplImg,(char*)bmpData,biHeader.biSizeImage/height); 

CopyData( iplImg->imageData, (char*)bmpData, biHeader.biSizeImage, 

isLowerLeft, height); 

/*int i,j; 

CvScalar s; 

int channels=biHeader.biBitCount / 8; 

int step=(biHeader.biWidth*channels+3) & -4; 

int loc=0; 

for(i=0;i<iplImg->height;i++){ 

for(j=0;j<iplImg->width;j++){ 

loc=i*step + j*channels; 

s.val[0]=bmpData[loc]; 

if(channels==3){ 

s.val[1]=bmpData[loc+1]; 

s.val[2]=bmpData[loc+2]; 

} 

cvSet2D(iplImg,i,j,s); 

} 

}*/ 

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; 

} 

} 



 ok。 


   花了一些时间来整理,希望对您有用。