一、
http://hi.baidu.com/lewvan/blog/item/f6591b4c4f17c2fad72afcd8.html
下面引自上述网址:
=========================================
该文章于2007年12月21日修改。
我所要介绍的是24位真彩色位图文件的结构。
一个24位真彩色位图文件包括以下三个部分:位图文件头、位图信息头和颜色数据域,这都是我自己起的名字,不知是否与经典有出入,大家应该能够意会。
首先说说位图文件头。就目前来看我所见到过的位图文件头都位于位图文件的最前部,长都是14个字节,例如有这样一个位图文件(用16位编辑器打开浏览时的效果):
0 1 2 3 4 5 6 7 8 9 A B C D E F
42 4D 86 00 00 00 00 00 00 00 36 00 00 00 28 00
00 00 05 00 00 00 05 00 00 00 01 00 18 00 00 00
00 00 50 00 00 00 C4 0E 00 00 C4 0E 00 00 00 00
00 00 00 00 00 00 FF 00 00 FF 00 00 FF 00 00 FF
00 00 FF 00 00 00 00 FF 00 00 FF 00 00 FF 00 00
FF 00 00 FF 00 00 00 00 FF 00 00 FF 00 00 FF 00
00 FF 00 00 FF 00 FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00
那么在第0行从左向右的前14个字节(红色部分)属于位图文件头,各个字节的意义是这样的:
42 4D:看作ASCII码,对应的字母为‘BM’,即表示该文件是位图文件;
86 00 00 00:四个字节用于表示改为图文件的大小尺寸,要注意的是它们是按低位到高位排列的,那么可以看出整个位图文件的尺寸是0x00000086字节,即134字节。不难得知,这四个字节最大可以表示4,294,967,296,即可以表示4GB的位图大小;
00 00 00 00:查资料知道,这4个字节是保留位,用于存储文件大小的数据。而我没有找到超过4G的位图,因此不知道这四个自己究竟如何使用。不过可以推测可能是用跟前面4字节共64 bit来表示文件的大小。FAT32文件系统下不支持超过4GB的文件,NTFS系统支持;
36 00 00 00:也是按从低位到高位排列的,用于表示改位图颜色数据域相对文件开始处的偏移量,可以看到这个位图的颜色数据域是从0x00000036字节处开始的(这里有点想不通,既然前面要用8个字节表示文件大小,为什么这里的偏移量只有4字节?)。
以上就是位图文件头的情况,接下来是位图信息头,仍旧观察前面的位图,从第一行E序字节的28开始(蓝色部分)共40字节,各个字节的含义是:
28 00 00 00:表示信息头的长度,0x00000028=40,即位图信息头占40个字节;
05 00 00 00:表示位图宽度,单位为像素。即位图的宽度为5个像素;
05 00 00 00:表示位图高度,单位为像素。即位图的高度为5个像素;
01 00:表示位图设备级别;
18 00:位图级别,0x0018=24,即24位真彩色;
00 00 00 00:表示压缩类型,为零表示不压缩;
50 00 00 00:用于表示颜色数据区的实际长度,16进制,单位为字节,这里是80字节;
00 00 00 00:表示水平分辨率,具体什么意思还不清楚;
00 00 00 00:表示垂直分辨率;
C4 0E 00 00:表示位图实际使用的颜色表中的颜色变址数。
C4 0E 00 00:表示位图显示过程中被认为重要颜色变址数。
最后是颜色数据域。有一点要说明,颜色数据区中每一行的数据长度必须是4的整数倍,为了做到这一点,颜色数据区每一行都可能需要进行补齐。例如上述图片宽5像素,高5像素,而每个像素占3个字节,这样似乎颜色数据区应该为5*5*3=75字节,但是文件信息头中记录的却是80字节,实际上多出的5个字节被分到了每一行用于补齐。还有一个尝试要提醒大家:位图颜色数据域是从位图的最后一行的最左端开始记录颜色信息的,而不是通常认为的位图第一行最左端。此外,色光三原色的记录顺序在文件中是蓝、绿、红。总的来说,观察上面的文件情况,可以看出文件的第一行为黑色,行末补了一个全零字节,第二行为白色,第三行为红色,第四行为绿色,第五行为蓝色,每一行的末尾都用一个全零字节补齐(不知道是否一定要补全零字节,我尝试胡乱修改补齐字节之后并未发现影响图片显示的情况)。
之所以研究查找这方面的资料,是因为我打算做一个能把非图片文件转换为24为真彩色DIB图片的小软件,这样就可以把诸如.EXE、.RAR、.TXT之类的文件上传到百度空间里了,不过仍然需要有一个网络空间来存储供用户下载的转换器,不知道这个软件到底有没有用,也不知道我研究这一堆有没有用。不过还是做出来吧!能看到.EXE文件转换成为图片的样子也是很令人兴奋的。
=========================================
二、
《bmp图像文件格式》
http://blog.csdn.net/xuzhihong_gdut/archive/2007/08/18/1749223.aspx
=========================================
BMP是bitmap的缩写形式,bitmap顾名思义,就是位图也即Windows位图。它一般由4部分组成:文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区组成。在系统中以BMP为扩展名保存。
打开Windows的画图程序,在保存图像时,可以看到三个选项:2色位图(黑白)、16色位图、256色位图和24位位图。这是最普通的生成位图的工具,在这里讲解的BMP位图形式,主要就是指用画图生成的位图(当然,也可以用其它工具软件生成)。建议刚开始通过UtralEdit-32等二进制软件来查看bmp图像以增加对该文件格式的了解。
BMP文件头结构;
接下来是BMP信息头
现在讲解BMP的4个组成部分:
1.文件头信息块(14个字节)
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; 文件类型,一定是‘BM’
DWORD bfSize; 文件大小,字节单位
WORD bfReserved1; 保留位
WORD bfReserved2; 保留位
DWORD bfOffBits; 位图矩阵偏移量,是相对于文件开头的偏移量,字节单位
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
0000-0001:文件标识,为字母ASCII码“BM”。
0002-0005:文件大小。
0006-0009:保留,每字节以“00”填写。
000A-000D:记录图像数据区的起始位置。各字节的信息依次含义为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。
2.图像描述信息块(40个字节)
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;
其中BITMAPINFOHEADER的结构体如下:
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize; 位图头大小,不一定有效的。
LONG biWidth; 位图宽度,象素单位
LONG biHeight; 位图高度,象素单位
WORD biPlanes; 平面数,一定为1
WORD biBitCount; 色彩深度,可以是1,4,8,16,分别表示单色,16色,256色和真彩色
DWORD biCompression; 压缩方式,0表示无压缩,1表示RLE压缩,2表示每个象素4比特的RLE压缩
DWORD biSizeImage; 图像区数据的大小
LONG biXPelsPerMeter; 水平分辨率,象素/米
LONG biYPelsPerMeter; 垂直分辨率,象素/米
DWORD biClrUsed; 所实际使用的颜色表中的颜色数,不一定有效
DWORD biClrImportant; 重要的颜色数,不一定有效
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
000E-0011:图像描述信息块的大小,常为28H。
0012-0015:图像宽度。
0016-0019:图像高度。
001A-001B:图像的plane总数(恒为1)。
001C-001D:记录像素的位数,很重要的数值,图像的颜色数由该值决定。
001E-0021:数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩)。
0022-0025:图像区数据的大小。
0026-0029:水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002A-002D:垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002E-0031:此图像所用的颜色数,如值为0,表示所有颜色一样重要。
3.颜色表
彩色表项的结构是
stypedef struct tagRGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号1的颜色,接下来表示颜色号2的颜色,依此类推。
4.图像数据区
颜色表接下来位为位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,即2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。
然而,未压缩的图像信息区的大小。除了真彩色模式外,其余的均大于或等于数据信息的大小。这是为什么呢?原因有两个:
1.BMP文件记录一行图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说,设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信息。
2.为了显示的方便,除了真彩色外,其他的每行中颜色模式的行字节数要用数据“00”补齐为4的整数倍。如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。
还有一点我要申明,当屏幕初始化为16或256色模式时,一定要设置调色板或修正颜色值,否则无法得到正确的图像颜色。
=========================================
三、有了上述基础,
下述delphi 7 代码就可以理解了: