BMP文件是位图文件,它自带了一种很无用的压缩功能——Run-Length Encode压缩算法。
BMP文件的结构是一个BITMAPFILEHEADER和一个BITMAPINFO,后面就是位图信息了。其中BITMAPINFO是一个BITMAPINFOHEADER和一个调色板。这几个结构体都定义在Windows.h里(可能并不是直接在里面定义的)
BITMAPINFOHEADER中的biCompression成员指定了这个位图是否经过压缩。它有四个数值:BI_RGB(没有压缩)、BI_RLE8(8位RLE压缩)、BI_RLE4(4位RLE压缩)、BI_BITFIELD(在BITMAPINFO的调色板位置指定了颜色值的红绿蓝的位域定义,这个不是“压缩”)。
如果BITMAPINFOHEADER.biCompression的值是BI_RLE8或BI_RLE4,那么BITMAPINFOHEADER.biSizeImage的值就是压缩过的全部位图数据的尺寸了。
它的压缩算法是这样的:
用非零字节表示重复的像素,比如03 55,相当于55 55 55,或者10 AA,那就是AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA。
而如果是零,那么紧接着后面的那个字节用于表示“特殊的情况”。如果是00 00,那么表示这是一行的结尾,如果是00 01,那是整个位图的结尾,而如果是00 02,那么紧接着后面的两个字节表示下一个要描述的像素的坐标偏移量(比如00 02 10 10,表示下一个要描述的像素的位置在相对当前像素(16,16)的位置)
如果紧接着后面的字节不是0、1、2,那么表示后面的字节是“没有经过压缩”的,这些字节应该是2字节对齐,不足的用00补全,比如00 05 12 34 56 78 9A 00,表示12 34 56 78 9A。
假设一个位图有如下的数据:
03 04 05 06 00 03 45 56 67 00 02 78 00 02 05 01
02 78 00 00 09 1E 00 01
那么它解压后应该是这样:
04 04 04 06 06 06 06 06 45 56 67 78 78 然后下一个像素的位置相对于当前是05 01
78 78 跳到下一行
1E 1E 1E 1E 1E 1E 1E 1E 1E 位图结束
用类似C语言的伪代码表示解压RLE8的过程是: