完整的位图文件解析

/ 1评 / 0

Published by orzz.org(). (https://orzz.org/%e5%ae%8c%e6%95%b4%e7%9a%84%e4%bd%8d%e5%9b%be%e6%96%87%e4%bb%b6%e8%a7%a3%e6%9e%90/)

与上次简单的位图加载不同,这次是完整的位图格式解析.暂时没有考虑压缩格式的位图.

下面的内容难免有错误,各位如发现纰漏请及时指出.


位图其实比较复杂,主要是由于各种原因导致的标准拓展和复杂化所致.

从磁盘上加载的BMP图片属于设备无关位图(DIB).通常来讲,DIB位图的基本结构如下:

其中,最上面的BITMAPFILEHEADER可以由后面的BITMAPINFO还原出来,没有BITMAPFILEHEADER的DIB被成为"压缩DIB".这里的压缩,指的是DIB的其余部分在连续的内存空间里紧挨着存放.

很多用于加载DIB的API,如LoadResource,LoadImage之类,它们返回的DIB句柄就是一个压缩的DIB.

BITMAPFILEHEADER 结构定义:

bfType是BMP文件的签名.对于目前的BMP文件,此字段只可能是两个ASCII字符'B'和'M'.其他的字段内容表示的文件仅被用在OS/2系统中.在校验BMP文件时可以直接通过检查文件最开头的16位字符是否为0x4D42来判断此文件是否为BMP文件.

bfSize存储了整个BMP文件的大小.

bfOffBits是Pixel数据段相对文件最开始的偏移量.

BITMAPINFO 结构定义:

BITMAPINFOHEADER为位图信息头.

位图信息头的版本相当多,最初的版本是BITMAPCOREHEADER,仅用于OS/2,从Win3.1开始是BITMAPINFOHEADER,被称为位图信息结构版本3;在后面还有配合Win95与NT中新特征而形成的版本4:BITMAPV4HEADER;以及配合Win98和Win2K中新特征而形成的版本5:BITMAPV5HEADER.

一般最经常看到的是BITMAPINFOHEADER,我们这里只简要介绍BITMAPINFOHEADER.

biSize在这里必须等于sizeof(BITMAPINFOHEADER),这是用来判断信息头版本的标记.其实更高版本的信息头只是在低版本上做了一些拓展,依然可以用低版本的方式解析.

biWidthbiHeight是以像素为单位的图像宽度和高度(BITMAPCOREHEADER中它们的类型是WORD,后面的版本都是LONG).biHeight可能取负值.当biHeight<0时表示像素阵列的扫描线由上至下进行.

biPlanes总是等于1.在MSDN中有这样的描述:"Specifies the number of planes for the target device. This value must be set to 1".DIB只支持单个位平面的图像.

biBitCount,表示一个像素所需要的二进制位数.可能有以下取值:1;2;4;8;16;24;32.

biCompression,压缩格式.BI_RGB与BI_BITFIELDS表示未压缩的位图.16位与32位位图的此字段可以是BI_BITFIELDS,此时在位图信息头之后将加入3个DWORD表示如何从Pixel中提取RGB的屏蔽位.

biSizeImage是像素阵列的大小.BI_RGB的位图此字段可以是0.由于像素字节数组中每个扫描行的字节数必需是4的倍数,不足将会用0补齐,因此真正的像素阵列行大小计算起来有点绕.有个通用的公式可以解决这个问题:pitch = 4 * ( (biWidth * biBitCount + 31) / 32 );当然,还有很多其他的计算方法,这里就不一一列举了.最后,biSizeImage = pitch * biHeight;

biClrUsed表示颜色表的项数.

biClrImportant表示显示位图实际需要的颜色表项数.

不同位数的位图,其像素阵列的存取都有所不同.

1,4,8位位图的像素阵列中存放的不是像素,而是此像素在颜色表中的索引.通过索引查找颜色表就可以得到这个像素点的颜色值.

16位位图是最为麻烦的.不仅位图数据分555与565(指RGB三个分量在每个16位像素中的排列方法)两种格式,位图类型也分BI_RGB与BI_BITFIELDS两种类型.并且最后得到的RGB数据还需要处理成合适的大小,因为16位中每个通道只有32或64级,但常规颜色是256级,因此需要按照色深进行转换.

24位位图比较简单,每个24位像素中RGB按888排列,即每个通道一个BYTE.

32位位图可以比24位位图多一个Alpha通道(但是不一定),因此可以显示半透明效果(RGBA).其他读取同24位位图一致.

下面给出各种不同位数位图像素阵列的读取方法.

首先是通用的数据预读取,这里定义一个宏来完成所有工作:

下面是具体的像素读取算法.

这里给出的代码是我个人程序中的代码,自己单独使用需要按照自己的需求对其中的一些预定义及底层调用做适当的修改.

全部的图像解析及底层库代码请访问:http://code.google.com/p/win32-standard-expansion/

Published by orzz.org(). (https://orzz.org/%e5%ae%8c%e6%95%b4%e7%9a%84%e4%bd%8d%e5%9b%be%e6%96%87%e4%bb%b6%e8%a7%a3%e6%9e%90/)

  1. darkcat说道:

    在参考了相关资料以后,发现上面32位位图解析有问题.
    32位位图内存像素的排列是 XRGB(X为无效位).

    因此正确的解析,在14-16行应该是:

    // …
    temp[inx + 1],
    temp[inx + 2],
    temp[inx + 3],
    // …

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据