位图文件由4个部分组成:位图文件头(BITMAPFILEHEADER)
位图信息头(BITMAPINFOHEADER)
调色板(LOGPALETE) (真彩图没有调色板)
实际位图数据
- 位图文件头结构(14字节)
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; //文件类型,值为0x4d42,即字符串BM
DWORD bfSize; //文件大小,即实际位图数据大小
WORD bfReserved1; //保留字
WORD bfReserved2; //保留字
DWORD bfOffBits; //从文件头到实际数据的偏移字节数,即位图文件头+位图信息头+调色板的大小
}BITMAPFILEHEADER; - 位图信息头结构(40字节)
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize; //这个结构的大小,固定值40
LONG biWidth; //图像宽度,单位为像素
LONG biHeight; //图像高度,单位为像素
WORD biPlanes; //调色板的数量,必须为1
WORD biBitCount; //颜色使用的位数,1表示黑白二色,4表示16色,8表示256色,24表示真彩色
DWORD biCompression; //是否压缩,通常为BI_RGB,即不压缩
DWORD biSizeImage; //实际位图数据的大小
LONG biXPelsPerMeter;//目标设备的水平分辨率,单位为像素/米
LONG biYPelsPerMeter;//目标设备的垂直分辨率,单位为像素/米
DWORD biClrUsed; //指定图像实际用到的颜色数,如果为0,表示为2的bitBitCount次方种
DWORD biClrImportant; //重要的颜色数,为0表示都重要
}BITMAPINFOHEADER - 调色板是一种GDI对象,可以认为它是一个颜色数组,列举了图像用到的所有颜色。但是对真彩色位图来说,是没有调色板的。此时,在位图信息之后直接是位图的 实际数据。调色板结构为LOGPALLETE
typedef struct tagLOGPALETTE
{
WORD palVersion; //表示系统的版本号
WORD palNumEntries; //表示调色板中包含的项目数,每一个项目表示一个颜色
PALETTEENTRY palPalEntry[l]; //表示PALETTEENTRY数组中的第一个颜色,PALETTEENTRY定义了颜色信息 - PALETTEENTRY结构定义如下
typedef struct tagPALETTEENTRY
{
BYTE pcRed; //表示红色分量
BYTE pcGreen; //表示绿色分量
BYTE pcBlue; //表示蓝色分量
BYTE pcFlags; //表示调色板中的项目如何被使用,可以为NULL
}PALETTEENTRY
对于使用了调色板的位图,位图实际数据描述的是像素值在调色板中的索引值,如果没有使用调色板,位图实际数据就是实际的RGB颜色值。
对于真彩色位图来说,没有调色板,一个像素需要3个字节来表示,在对位图数据进行操作时应该注意以下问题:
1.位图数据每行的字节数必须是4的整数值
以真彩色位图为例,如果位图的宽度为150,由于一个像素需要3个字节,因此一行需要450个字节,但是450并不是4的整数倍,需 要填充2个字节,变为452,为4的整数倍。这样一行需要填充2个字节。正式基于这个原因,在旋转位图时会导致源位图与目标位图的大小不一致,以150*100大小的位图为例,旋转后的图像大小为100*150,尤其旋转后的宽度为100,每行需要300个字节,正好是4的整数倍,因此不再需要填充字节了,这样就导致转换后的位图比原来的位图小。
2.位图数据是从下向上存储的
对于位图数据来说,最低端的数据表示的是位图的第一行颜色数据。最上方的数据表示的是位图的最后一行颜色数据,每一行数据表示的颜色仍是按照从左向右存储的。
3.对于真彩色位图来说,每一行数据是按照RGB的颜色数序表示的
真彩色位图每一行数据表示的颜色都是按照蓝、绿、红顺序。