如何解决使用位深来确定 BMP 图像中颜色表的大小是否有效?
我正在编写一个程序来读取 BMP,我发现有时并不总是指定颜色映射条目(偏移量 0x002E
)的数量。我选择使用位深度信息(偏移量 0x001C
)通过 0x1 << BitDepth
确定地图中的颜色数量。
似乎一切正常,但这样做是否有看不见的后果?另外,省略颜色映射条目的数量是否正常?
解决方法
让我们看看定义 BMP 格式的 Windows Metafile Format。我检查了 2013 年的 v11.0 和最新的 v17.0。特别是,您似乎对 BITMAPINFOHEADER
类型的 DIB 标头(大小为 0x28 字节,在 2.2.2.3 节中描述)感兴趣。 BITMAPCOREHEADER
(最原始的 BIP 头)仅指定颜色位深度,其他版本的头要么是专有扩展(BITMAPV2INFOHEADER
、BITMAPV3INFOHEADER
、OS22XBITMAPHEADER
、等)或仅添加更多字段的扩展程序(BITMAPV4HEADER
、BITMAPV5HEADER
)。
我们感兴趣的两个字段是BitCount
(offset 0x1C,你所说的BitDepth
)和ColorUsed
(offset 0x2E),定义如下:
BitCount(2 个字节):一个 16 位无符号整数,用于定义定义每个像素的位数和 DIB 中的最大颜色数。该值必须在 BitCount 枚举中(第 2.1.1.3 节)
[...]
ColorUsed(4 个字节):一个 32 位无符号整数,指定 DIB 使用的颜色表中的索引数,如下所示:
- 如果此值为零,则 DIB 使用与 BitCount 值对应的最大颜色数。
- 如果此值不为零且 BitCount 值小于 16,则此值指定 DIB 使用的颜色数。
- 如果此值不为零且 BitCount 值为 16 或更大,则此值指定用于优化系统调色板性能的颜色表的大小。
注意:如果此值非零且大于基于 BitCount 值的颜色表的最大可能大小,则应假定最大颜色表大小。
仅从这里就应该清楚了,一般只考虑BitCount
来确定颜色表的大小是不够的。
更详细地说,BitCount
的唯一有效值是:
typedef enum {
BI_BITCOUNT_0 = 0x0000,BI_BITCOUNT_1 = 0x0001,BI_BITCOUNT_2 = 0x0004,BI_BITCOUNT_3 = 0x0008,BI_BITCOUNT_4 = 0x0010,BI_BITCOUNT_5 = 0x0018,BI_BITCOUNT_6 = 0x0020
} BitCount;
现在关于颜色表的实际大小,您需要参考文档的2.1.1.3部分,对以上数值一一进行了详细说明,针对每种情况解释是否需要颜色表、它应该是什么尺寸、如何解释它等等。
我不会引用文档的整个部分,因为它很长并且可以免费查看,但这里有一个摘要:
-
BitCount
是BI_BITCOUNT_0
:没有颜色表。 -
BitCount
为BI_BITCOUNT_1
或BI_BITCOUNT_2
或BI_BITCOUNT_3
:颜色表大小为1 << BitCount
-
BitCount
是BI_BITCOUNT_4
或BI_BITCOUNT_5
或BI_BITCOUNT_6
:-
ColorUsed == 0
:颜色表大小为1 << BitCount
-
ColorUsed != 0
:颜色表大小为min(ColorUsed,1 << BitCount)
-
结论...
似乎一切正常,但这样做是否有看不见的后果?
是的,有一些警告,仅仅执行 1 << BitCount
是不够的,您应该遵循规范(废话!)。
另外,省略色图条目的数量是否正常?
不确定这样做是“正常”还是“常见”的著名 BMP 实现,但根据规范,它肯定是合法的。注意:这里的“省略”是指将 ColorUsed
设置为 0
,除非您使用的是没有 ColorUsed
字段的不同类型的 DIB 标头。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。