位图存储格式2009-08-26 02:31 BMP位图文件的存储格式摘要:本文简单介绍了位图文件的两种存储格式,并且在VC++6.0下实现了读取位图文件中的数据,用SetPixel()函数在窗口中重现图像,最后在程序中实现了一种存储格式到另一种存储格式的转换。
关键字:BMP、灰度位图、24位真彩色位图、存储格式一、前言BMP(Bitmap的缩写)图像是指文件名后缀为BMP的位图图像。
位图图像在计算机中使用很广泛,例如在windows中,记事本、写字板中的文字就是用位图图像表示出来的。
许多以其它格式存储的图像,就是在位图图像的基础上,进行优化处理后得到的,例如JPEG图像等。
在数字图像处理中,许多算法就是针对24位真彩色位图或灰度位图设计的。
因此,很有必要介绍一下位图文件的这两种存储格式。
二、24位真彩色图像存储格式把下图的24位真彩色图像格式在16位编辑器(例如VC编辑器)中打开,可以看到图像的二进制数据。
24位真彩色的二进制数据为:这是24位真彩色位图文件数据一部分。
这一部分数据包括位图文件头、位图信息头和位图阵列三部分。
(一)位图文件头位图文件头用来记录标志文件大小的一些信息,在文件中占14个字节,存储的内容如下:字节1234567891011121314000000424DCCB402000000000036000000其中:42 4D 为位图的标志,即ASCII码为BMCC B4 02 表示位图文件的总字节数,换算成十进制为(02B4CC)H=(177356)10,即这副图像的大小为177356字节。
00 00 00 00 00 为保留字节,用来存储文件大小的数据。
36 00 00 00 00 表示位图阵列的起始位置,(36)H=(54)10即54字节开始为位图阵列。
(二) 位图信息头位图信息头记录和位图相关的一些信息,在文件中占40个字节,存储的内容如下:字节12345678910111213141516000000280000001600002C010000C5000000010018000000000032000000000000120B0000120B00000000000048000000000000其中:28 00 00 00 表示信息头的长度,(28)H=(40)10,即位图信息头占40个字节。
2C 01 00 00 表示位图宽度,单位为像素。
(012C)H=(300)10,即位图的宽度为300个像素。
C5 00 00 00 表示位图高度,单位为像素。
(C5)H=(197)10,即位图的宽度为197个像素。
01 00 表示位图设备级别18 00 位图级别,(0018)H=(24)10,即24位真彩色。
00 00 00 00 表示压缩类型,为零表示不压缩。
00 00 00 00 保留字节。
12 0B 00 00 表示水平分辨率12 0B 00 00 表示垂直分辨率00 00 00 00 表示位图实际使用的颜色表中的颜色变址数。
00 00 00 00 表示位图显示过程中被认为重要颜色变址数。
(三)位图像素阵列剩下的部分为位图像素阵列,即像素表示部分,每个象素点由3个字节的数据组成,按照从左到右的顺序,分别表示蓝色、绿色、红色。
在VC++中的wingdi.h中对于位图的编码和格式有更加详细的定义,下面给出24位真彩色位图格式在VC++中的定义。
typedef struct tagBITMAPFILEHEADER {//位图文件头WORD bfType; //位图标志“BM”DWORD bfSize; //位图文件总字节数WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits;} BITMAPFILEHEADER;typedef struct tagBITMAPINFOHEADER{ //位图信息头格式定义DWORD biSize; //位图信息头占用字节数LONG biWidth; //位图图像宽度(以像素为单位)LONG biHeight; //位图图像高度(以像素为单位)WORD biPlanes; //位图设备级别WORD biBitCount //位图级别设定,每个像素所需的位数,必须是1(双色),// 4(16色),8(256色)或24(真彩色)之一DWORD biCompression; //压缩类型DWORD biSizeImage; //位图阵列表字节数LONG biXPelsPerMeter; //水平分辨率LONG biYPelsPerMeter; //垂直分辨率DWORD biClrUsed; //位图实际使用的颜色表中的颜色变址数DWORD biClrImportant; //位图显示过程中被认为重要颜色变址数} BITMAPINFOHEADER;typedef struct tagRGBTRIPLE { //位图阵列格式定义BYTE rgbtBlue; //定义蓝色BYTE rgbtGreen; //定义绿色BYTE rgbtRed; //定义红色} RGBTRIPLE;//构成一个3字节的RGBTRIPLE。
按照这个这个结构可以从BMP文件中读取数据,然后在屏幕上用SetPixel()函数描绘出来。
主要代码如下:if (!cf.Open(TransValue,CFile::modeRead, &e))//找到文件后,打开文件{MessageBox("Can not open the file!","Open File");return;}cf.SeekT oBegin();cf.Read(&bmfh,sizeof(bmfh));//读取文件头cf.Read(&bmih,sizeof(bmih));//读取文件信息头rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];cf.SeekT oBegin();cf.Seek(54,CFile::begin);//读取文件数据if (cf.GetLength()>64*1024){cf.ReadHuge(rgb,bmih.biWidth*bmih.biHeight*3);//}else{cf.Read(rgb,bmih.biWidth*bmih.biHeight);}//在屏幕上打点显示图像for (int i=0; i<bmih.biHeight;i++){for (int j=0; j<bmih.biWidth; j++){pDC->SetPixel(j,bmih.biHeight-i,RGB(rgb[i*bmih.biWidth+j].rgbtRed,rgb[i*bmih.biWidth+j].r gbtGreen,rgb[i*bmih.biWidth+j].rgbtBlue));}}cf.Close();//关闭文件delete rgb;//释放内存三、灰度位图存储格式同样,把下面的灰度位图在VC编辑器中以Binary方式打开,可以看到如下的数据(部分):灰度位图数据:从上述数据中可以看出,灰度位图的存储格式与24位真彩色位图的存储格式基本相同。
唯一的差别是,灰度位图比24位真彩色位图增加了一部分:颜色索引表。
因此,灰度位图的像素阵列的起始位置不是第(36)H=(54)10个字节,而是第(436)H=(1078)10个字节,同时灰度位图用一个字节来表示一个像素。
这样,灰度位图的像素阵列小了三分之二。
颜色索引表定义为:typedef struct rgbn{BYTE red;BYTE green;BYTE blue;BYTE null;} RGBn;在实际的编程中,读取数据的方式发生了变化,除了要读取文件头,文件信息头外,还要设置变量读取颜色索引表。
除此以外,灰度图像的编程读取显示方式与24位真彩色位图的方式完全相同,在此就不再描述。
从上述灰度位图和24位真彩色位图的存储结构中可以看出,把24位真彩色位图的颜色信息去掉,就可以得到灰度位图。
根据不同的需要,不同的理论,有不同的去掉颜色的方法。
在本文中,仅仅在红、绿、蓝三种基本色前加权三分之一,然后在屏幕上打点显示出来,得到灰度位图图像。
如果需要存储,只需要在文件头、文件信息头后加上颜色索引表,然后再以一个字节的空间存储位图像素信息,把上述信息按顺序写到一个文件中,就得到一个灰度位图图像文件。