使用位深度来确定 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 标头)仅指定颜色位深度,其他版本的标头要么是专有扩展(BITMAPV2INFOHEADERBITMAPV3INFOHEADEROS22XBITMAPHEADER 等),要么只是添加更多的扩展字段(BITMAPV4HEADERBITMAPV5HEADER)。

我们感兴趣的两个字段是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部分,上面对上面的数值进行了详细的描述,解释每种情况是否需要颜色表、它应该是什么尺寸、如何解释它等等。

我不会引用文档的整个部分,因为它很长并且可以免费查看,但这里有一个摘要:

BitCountBI_BITCOUNT_0:没有颜色表。

BitCountBI_BITCOUNT_1BI_BITCOUNT_2BI_BITCOUNT_3:颜色表大小为1 << BitCount

BitCountBI_BITCOUNT_4BI_BITCOUNT_5BI_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)

调整 bmp 图像大小

图像深度

BMP文件中图像数据是按啥顺序存放的?

一种颜色的图片我保存为gif和png格式的图片,为啥颜色会有偏差呢