使用位深度来确定 BMP 图像中颜色表的大小是不是有效?
Posted
技术标签:
【中文标题】使用位深度来确定 BMP 图像中颜色表的大小是不是有效?【英文标题】:Is it valid to use bit-depth to determine the size of the colour table in a BMP image?使用位深度来确定 BMP 图像中颜色表的大小是否有效? 【发布时间】:2021-07-23 15:17:50 【问题描述】:我正在编写一个读取 BMP 的程序,但我发现有时并不总是指定颜色映射条目的数量(偏移量0x002E
)。我选择使用位深度信息(偏移量0x001C
)通过0x1 << BitDepth
确定地图中的颜色数量。
一切似乎都运行良好,但这样做会产生看不见的后果吗?另外,省略颜色映射条目的数量是否正常?
【问题讨论】:
您需要的一切都记录在这里:docs.microsoft.com/en-us/windows/win32/api/wingdi/… 您可以通过参考***页面来协调文件头中的 BITMAPINFOHEADER:en.wikipedia.org/wiki/BMP_file_format 【参考方案1】:让我们看一下定义 BMP 格式的Windows Metafile Format。我检查了 2013 年的 v11.0 和最新的 v17.0。特别是,您似乎对 BITMAPINFOHEADER
类型的 DIB 标头(大小为 0x28 字节,在第 2.2.2.3 节中描述)感兴趣。 BITMAPCOREHEADER
(最原始的 BIP 标头)仅指定颜色位深度,其他版本的标头要么是专有扩展(BITMAPV2INFOHEADER
、BITMAPV3INFOHEADER
、OS22XBITMAPHEADER
等),要么只是添加更多的扩展字段(BITMAPV4HEADER
、BITMAPV5HEADER
)。
我们感兴趣的两个字段是BitCount
(偏移量0x1C,你指的是BitDepth
)和ColorUsed
(偏移量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
是不够的,你应该遵循规范(duh!)。
另外,省略颜色图条目的数量是否正常?
不确定这样做是“正常”还是“常见”形式的著名 BMP 实现,但根据规范肯定是合法的。注意:这里的“省略”我假设您的意思是将ColorUsed
设置为0
,除非您使用的是不具有ColorUsed
字段的不同类型的DIB 标头。
【讨论】:
以上是关于使用位深度来确定 BMP 图像中颜色表的大小是不是有效?的主要内容,如果未能解决你的问题,请参考以下文章
图像位深度 8位 16位 24位 32位区别对比 RGB 真彩色 基本概念:(大小,深度,通道)位深度数据类型转换原理 Mat数据读取(opencv里的imread)