<The first part> Bitmap file header BITMAPFILEHEADER, this structure has a fixed length of 14 bytes
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
variable | Size (14 bytes total) | effect |
bfType | 2bytes | File type description, available values: BM - windows 3.1x,95,NT,... BA - OS/2 Bitmap Array CI - OS/2 Color Icon CP - OS/2 Color Pointer IC - OS/2 Icon PT - OS/2 Pointer |
bfsize | 4bytes | Description file size, unit: byte |
bfReserved1 | 2bytes | Reserved, must be set to 0 |
bfReserved2 | 2bytes | Reserved, must be set to 0 |
bfOffBits | 4bytes | Indicates the byte offset from the file header to the actual image data. Because the length of the bitmap information header and palette is not fixed, it helps to quickly locate the bitmap data |
<The second part> is the bitmap information header BITMAPINFOHEADER, which is also a structure, which is defined as follows:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
variable | size | effect |
biSize | 4 bytes | The number of bytes required for the BITMAPINFOHEADER structure |
biWidth | 4 bytes | image width, in pixels |
biHeight | 4 bytes | Image height, in pixels Note: If the value is positive, the image is reversed; if it is negative, the image is positive Most bmp images are inverted bitmaps; |
biPlanes | 2 bytes | Specifies the number of color planes for the target device, value 1 |
biBitCount | 2 bytes | Specifies the number of bits/pixel as 1, 4, 8, 16, 24 or 32 |
biCompression | 4 bytes | Indicates the image data compression type, the value range: 0 BI_RGB not compressed 1 BI_RLE8 8-bit run-length encoding (RLE), only for 8-bit bitmaps 2 BI_RLE4 4-bit run-length encoding (RLE), only for 4-bit bitmaps 3 BI_BITFIELDS bit field for 16/32 bit bitmap 4 BI_JPEG JPEG bitmap with jpeg image (for printer only) 5 BI_PNG PNG bitmap with png image (for printers only) |
biSizeImage | 4 bytes | Description image size biSizeImage=biWidth' × biHeight, unit byte, when BI_RGB is used, it can be set to 0 |
biXPelsPerMeter | 4 bytes | Indicates the horizontal resolution (pixels/meter), signed integer |
biYPelsPerMeter | 4 bytes | Indicates the vertical resolution (pixels/meter), signed integer |
biClrUsed | 4 bytes | Indicates the color index in the color table actually used by the bitmap, if it is 0, see the subsequent description |
biClrImportant | 4 bytes | Indicates the number of color indices that have an important impact on image display, 0 means all are important |
<第三部分>为调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。有些位图,如真彩色图,前面已经讲过,是不需要调色板的,BITMAPINFOHEADER后直接是位图数据。可以理解为biClrUsed参数不为0时,有调色板。
调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有2biBitCount个元素)。数组中每个元素的类型是一个RGBQUAD结构,占4个字节,其定义如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue; //该颜色的蓝色分量
BYTE rgbGreen; //该颜色的绿色分量
BYTE rgbRed; //该颜色的红色分量
BYTE rgbReserved; //保留值
} RGBQUAD;
比如索引值biClrUsed为64,即有64个调色盘,则总偏移量计算14bytes+40bytes+64*4bytes=310bytes
<第四部分>实际的图象数据。
(1)对于用到调色板的位图,图象数据就是该象素颜在调色板中的索引值。即某一点只储存一个索引值,按照这个索引值在调色板中查找对应像素作为它的像素
(2)对于真彩色图,图象数据就是实际的R、G、B值。下面针对2色、16色、256色位图和真彩色位图分别介绍。 每个像素点都是按调色板的格式储存的,也可以理解为全是调色板
对于2色位图,用1位就可以表示该象素的颜色(一般0表示黑,1表示白),所以一个字节可以表示8个象素。
对于16色位图,用4位可以表示一个象素的颜色,所以一个字节可以表示2个象素。
对于256色位图,一个字节刚好可以表示1个象素。
要注意两点:
(1) 每一行的字节数必须是4的整倍数,如果不是,则需要补齐。这在前面介绍biSizeImage时已经提到了。
(2) 一般来说,.BMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推 ,最后得到的是最上面一行的最右一个象素。
<对齐>
Windows默认的扫描的最小单位是4字节,如果数据对齐满足这个值能够大幅提升图像读取速度。因此,BMP图像顺应了这个要求,要求每行的数据的长度必须是4的倍数,如果不够需要进行比特填充(以0填充)。填充后的每行的字节数为:rowsize=4*ceil(BPP*Width/32)
<其他情况>
上述主要是PC机上的位图文件的构成,对于嵌入式平台,可能在调色板数据段与PC机的不同。如在嵌入式平台上常见的16位r5g6b5位图实际上采用的掩模的方式而不是索引的方式来表示图像。此时,在调色板数据段共有四个部分,每个部分为四个字节,实际表示的是彩色版规范。即:
第一个部分是红色分量的掩模
第二个部分是绿色分量的掩模
第三个部分是蓝色分量的掩模
第四个部分是Alpha分量的掩模(缺省为0)
1111100000000000(二进制),是蓝红分量的掩码。
0000011111100000(二进制),是绿色分量的掩码。
0000000000011111(二进制),是蓝色分量的掩码。
在每个像素值的两个字节16位中,按从高到低取5、6、5位分别就是r、g、b分量值;把分量值r、g、b值分别左移操作3、2、3位就可以补齐每个分量为一个字节,再把这三个字节按BGR组合,就可以转换为24位标准BMP格式