Bitmap 文件结构

0x81 位图

Bitmap,即位图,是非常常见的一种图片文件结构。在我平时的Android开发当中,最常见的性能问题就是Bitmap资源的问题。一种不太严谨的说法是,所有压缩格式的图片经过解码后都是以Bitmap的形式存在于内存当中,之所以有这种说法,就是因为Bitmap是一步一个字节的图片存储方式,没有JPEG那种区域颜色涂抹。

位图又叫做光栅图,它以像素为单位一个点一个点的描述图像信息,因此也有人称他为点阵图。还有一种图片格式与之对立,叫做矢量图或向量图,它采用数学方法进行描述而不是记录每一个像素信息,因此它可以无限放大而不失真。一般的,我们又称他们为图像和图形,意为图片像素和图片形状。

0x82 位图文件

狭义上讲,我们平时所说的位图文件就是BMP文件,它以.bmp作为文件扩展名,是Windows采用的图像文件存储格式,在后来BMP才具有通用性成为了设备无关位图,而默认的扩展名依然是.bmp,当然也可以使用.dib(Device Independent Bitmap)。

0x83 位图结构

BMP文件和其他一些常见格式是一样的,文件的最开始是文件头,它通常由4部分组成——位图文件头、位图信息头、色表和位数据(24Bits Windows Bitmap 没有色表)。

我们先看测试文件的文件信息:

BMP文件基本信息

我们用Vim打开一个BMP文件看看它的内容:

BMP文件内容

我们可以发现整个文件几乎全是乱码,但是文件开头两个字母是“BM”,我们使用%!xxd命令查看该文件的16进制视图:

BMP文件16进制内容

接下来我们分析文件信息(括号内为结构体信息),注意字节顺序:

  1. 位图文件类型(WORD bfType)
    1-2字节,424d,代表BM且必须是BM。

  2. 位图文件大小(DWORD bfSize)
    3-6字节,3641 0300,单位是字节,文件大小
    其中文件信息中的大小是213.3 KB (213,302 字节,Linux下1000进制矫正磁盘存储),而213302d=34136h:

    大小换算

  3. 保留字1/2(WORD bfReserved1/2)
    7-10字节,0000 0000,始终为0。

  4. 数据偏移(DWORD bfOffBits)
    11-14字节,3600 0000,一般为54。到数据偏移为止,位图文件头共7字14字节。

  5. 位图信息头大小(DWORD biSize)
    15-18字节,2800 0000,一般为40,固定大小。

  6. 位图宽(LONG biWidth)
    19-22字节,0501 0000,文件信息中宽为261,而261d=105h。

  7. 位图高(LONG biHeight)
    23-26字节,1001 0000,文件信息中高为272,而272d=110h。

  8. 设备级别(WORD biPlanes)
    27-28字节,0100,固定为1。

  9. 位图类型(WORD biBitCount)
    29-30字节,1800,位图像素类型。其中1代表双色,4代表16色,8代表256色,16代表全彩色,24代表真彩色。

  10. 位图压缩类型(DWORD biCompression)
    31-34字节,0000 0000,采用的压缩类型,通常是不压缩。其中0代表不压缩,1代表RLE8,2代表RLE4。

  11. 位图图片大小(DWORD biSizeImage)
    35-38字节,0041 0300,34136h-54d=34100h。

  12. 其他信息
    39-54字节,大部分为0。

  13. 颜色表暂不讨论

  14. 数据部分
    24位真彩色使用RGB颜色,一个像素占用三个字节,所以在16进制信息里就是三个字街一组分别代表BGR。由于Windows在32位下每4个字节为一组处理速度比较块,所以每行颜色的末尾可能使用0补位(这里暂不细谈)。

  15. 扫描顺序
    行内正序,行间逆序(即由下至上)。

0x84 BMP文件修改

有了文件结构,我们就可以在这个基础上进行一些小tricks啦~