BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。
BMP位图文件默认的文件扩展名是.BMP,有时它也会以.DIB或.RLE作扩展名。
BMP格式的文件从头到尾依次是如下信息:
24与32位真彩色位图没有颜色表,所以只有1、2、4这三部分。
bmp文件头结构体为BITMAPFILEHEADER,共14字节,定义如下:
typedef struct tagBITMAPFILEHEADER {
WORD bfType; //文件标识,规定为0x4D42,字符显示就是'BM'
DWORD bfSize; //文件大小
WORD bfReserved1; //保留,必须设置为0
WORD bfReserved2; //保留,必须设置为0
DWORD bfOffBits; //从头到点阵数据的偏移
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
位图信息头包括BITMAPINFOHEADER结构体与掩码(可选)两部分。BITMAPINFOHEADER结构体一共40字节,定义如下:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; //位图信息头的大小,一般为40
LONG biWidth; //位图的宽度,单位:像素
LONG biHeight; //位图的高度,单位:像素
WORD biPlanes; //颜色平面数,一般为1
WORD biBitCount; //比特数/像素数
DWORD biCompression; //压缩类型,BI_RGB(0)为不压缩
DWORD biSizeImage; //位图数据的大小,当用BI_RGB格式时,可以设置为0
LONG biXPelsPerMeter; //水平分辨率,单位:像素/米
LONG biYPelsPerMeter; //垂直分辨率,单位:像素/米
DWORD biClrUsed; //调色板的颜色数,为0则颜色数为2的biBitCount次方
DWORD biClrImportant; //重要的颜色数,0代表所有颜色都重要
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
biSize:一般为40,如果大于40,说明后面有3个DWORD的掩码。一般16位与32位位图有掩码,代表RGB分别占用哪几位,此时biCompression=BI_BITFIELDS。
biHeight:一般大于0,代表位图倒立,图像数据是从左下角到右上角排列的;如果为负说明正向,位图高度为-biHeight。
biPlanes:bmp文件为1。但是ico/cur文件可能大于1。
biBitCount:1位(单色),2位(4色,CGA),4位(16色,VGA),8位(256色),16位(增强色),24位(真彩色)和32位等。
16位位图常用的有555与565两种存储格式。这两种的主要区别在biCompression,如果biCompression=BI_RGB,此时位图为555的位图,如果biCompression=BI_BITFIELDS,此时位图可能为565的位图(要求掩码为0xF800、0x07E0、0x001F),此时有掩码出现。
16、24与32位位图没有调色板。调色板就是一个颜色的索引,为结构体RGBQUAD的数组,数组长度为biClrUsed,如果biClrUsed=0则数组长度为2的biBitCount次方。RGBQUAD结构体定义如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
如果biHeight>0,代表位图倒立,图像数据是从左下角到右上角排列的;相反,如果biHeight<0,代表位图正向,图像数据是从左上角到右下角排列的。
如果是24位色图,按照BGR的顺序排列,32位色图按照BGRAlpha排列。
位图数据排列还有一个规则,就是对齐。
Windows默认的扫描的最小单位是4字节,如果数据对齐满足这个值的话对于数据的获取速度等都是有很大的增益的。因此,BMP图像顺应了这个要求,要求每行的数据的长度必须是4的倍数,如果不够需要进行比特填充(以0填充),这样可以达到按行的快速存取。这样的话,位图数据的大小就不一定是宽x高x每像素字节数了,因为每行还可能有0填充。
填充后的每行数据如下:
其中,BPP是每像素的比特数(Bits Per Pixel),即biBitCount,Width是宽度,单位是像素即bfWidth。
ICO是Windows的图标文件格式,图标文件可以存储单个图案、多尺寸、多色板的图标文件。一个图标实际上是多张不同格式的图片的集合体,并且还包含了一定的透明区域。
ICON文件结构有点类似BMP文件,不过因为ICON文件支持多资源,所以比BMP文件多了一个索引目录的结构,以供检索文件内的各个图标资源。图像数据部分除了多一段1bpp的掩码部分以外,剩余的部分和BMP文件的位图信息段及图像信息段是相同的。
Icon文件结构由两部分组成:icon文件头和多张bmp图片数据。bmp图片数据没有BITMAPFILEHEADER文件头,只有BITMAPINFOHEADER信息头。
Icon文件头结构体如下:
typedef struct
{
BYTE bWidth; //图像宽度,单位:像素
BYTE bHeight; //图像高度,单位:像素
BYTE bColorCount; //颜色数
BYTE bReserved; //保留,为0
WORD wPlanes; //平面数,一般为1
WORD wBitCount; //每像素比特数
DWORD dwBytesInRes; //数据块大小
DWORD dwImageOffset;//数据块偏移量
} ICONDIRENTRY, *LPICONDIRENTRY;
typedef struct
{
WORD idReserved; //保留,为0
WORD idType; //文件类型,图标为1,光标为2
WORD idCount; //图象个数
ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
} ICONDIR, *LPICONDIR;
每个Icon文件都起始于ICONDIR结构体,然后接idCount个
ICONDIRENTRY结构体数组,然后再接idCount个数据块,每个数据块都是没有
BITMAPFILEHEADER文件头的bmp图片数据。
Icon文件中的bmp图片数据,包括信息头、调色板、XOR点阵数据、AND点阵掩码4部分,与bmp文件中的信息头、调色板、点阵数据相同。不同点在于,信息头中的biheight变量,而在ICON文件里,可能由于采用了两段掩码图像数据的缘故,该变量的值一般设定为高度象素量的2倍。
掩码的用途:
' AND位掩码 XOR位掩码 显示'
' 0 0 黑色'
' 0 0-F 调色板指定色'
' 1 0 屏幕,透明'
' 1 1 屏幕的反色,一般不用。
光标文件扩展名一般为.cur。与图标文件Icon一样,是特殊类型的小位图。一般情况下,你可以把一个图标文件改名后直接作为鼠标指针来使用。当然,一些色彩丰富的大图标,如果用作鼠标指针的话,在硬件不足的情况下,会出现闪烁的现象。
对于光标文件来说,它与图标文件(*.ico)的不同点主要在于:它使用了热点标志。热点标志是指你按下鼠标按钮时,真正的按下是在光标图形的那一个点上发生的。因为鼠标是一幅图形,所以,需要为它指定一个具体的点(相对于这个图形左上角的位置在X方向和Y方向的偏移量)。如果不指定,这两个值就是0,那么,热点就在鼠标指针的左上角。对于一些特别的鼠标指针来说,这样显然是不合适的,例如在MS Office中当鼠标位于页面的左边附近时,会显示一个向右的箭头,这样的情况下,热点如果还在左上角,就与人们的直观理解有区别了。
光标文件与图标文件的数据结构及其相似,不同点在于:ICONDIR结构体中的idType成员光标为2,而图标为1。ICONDIRENTRY结构体中的wPlanes与wBitCount不再代表原有含义,wPlanes代表热点的X坐标,wBitCount代表热点的Y坐标。