您的位置:首页 > 其它

BMP位图文件的存储格式

2008-08-05 11:03 204 查看
摘 要:本文简单介绍了位图文件的两种存储格式,并且在VC++6.0下实现了读取位图文件中的数据,用SetPixel()函数在窗口中重现图像,最后在程序中实现了一种存储格式到另一种存储格式的转换。

一、前言

BMP(Bitmap的缩写)图像是指文件名后缀为BMP的位图图像。位图图像在计算机中使用很广泛,例如在windows中,记事本、写字板中的
文字就是用位图图像表示出来的。许多以其它格式存储的图像,就是在位图图像的基础上,进行优化处理后得到的,例如JPEG图像等。

在数字图像处理中,许多算法就是针对24位真彩色位图或灰度位图设计的。因此,很有必要介绍一下位图文件的这两种存储格式。

二、24位真彩色图像存储格式

把下图的24位真彩色图像格式在16位编辑器(例如VC编辑器)中打开,可以看到图像的二进制数据。

24位真彩色的二进制数据为:

这是24位真彩色位图文件数据一部分。这一部分数据包括位图文件头、位图信息头和位图阵列三部分。

(一)位图文件头

位图文件头用来记录标志文件大小的一些信息,在文件中占14个字节,存储的内容如下:

字节

1

2

3

4

5

6

7

8

9

10

11

12

13

14

000000

42

4D

CC

B4

02

00

00

00

00

00

36

00

00

00

其中:

42 4D 为位图的标志,即ASCII码为BM

CC B4 02 表示位图文件的总字节数,换算成十进制为(02B4CC)H=(177356)10,即这副图像的大小为177356字节。

00 00 00 00 00 为保留字节,用来存储文件大小的数据。

36 00 00 00 00 表示位图阵列的起始位置,(36)H=(54)10即54字节开始为位图阵列。

(二) 位图信息头

位图信息头记录和位图相关的一些信息,在文件中占40个字节,存储的内容如下:

字节

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

000000

28

00

000016

00

00

2C

01

00

00

C5

00

00

00

01

00

18

00

00

00

000032

00

00

00

00

00

00

12

0B

00

00

12

0B

00

00

00

00

000048

00

00

00

00

00

00

其中:

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

cf.Read(&bmfh,sizeof(bmfh));//读取文件头

cf.Read(&bmih,sizeof(bmih));//读取文件信息头

rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];

cf.SeekToBegin();

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].rgbtGreen,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位真彩色位图的颜色信息去掉,就可以得到灰度位图。根据不同的需要,不同的理论,有
不同的去掉颜色的方法。在本文中,仅仅在红、绿、蓝三种基本色前加权三分之一,然后在屏幕上打点显示出来,得到灰度位图图像。如果需要存储,只需要在文件
头、文件信息头后加上颜色索引表,然后再以一个字节的空间存储位图像素信息,把上述信息按顺序写到一个文件中,就得到一个灰度位图图像文件。

关键字:BMP、灰度位图、24位真彩色位图、存储格式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: