BMP header 应该是什么样子?

How should BMP header look like?

我正在尝试编写代码来读取 BMP 文件,所以我正在尝试读取 BMP header(s)。我正在使用来自某个代码库的测试图像,但它看起来像该结构与维基百科 Wikipedia BMP structure 上有关 BMP 图像结构的信息不对应,特别是部分,应该在哪里存储偏移量(“偏移量,即可以找到位图图像数据(像素数组)的字节的起始地址。”)在维基百科的 table 中作为图像的开头如下所示:

00000000: 424d ea88 0000 0000 0000 3604 0000 2800  BM........6...(.
00000010: 0000 e300 0000 9500 0000 0100 0800 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0001  ................
00000030: 0000 0000 0000 2c2a 2c00 4c8f 6900 252e  ......,*,.L.i.%.
00000040: 9900 385b 4700 4c54 9700 98c9 a000 7a8c  ..8[G.LT......z.

所以很明显图像从 36h 而不是 436h 开始,根据 Wikipedia 应该看起来像这样 - 在我看来有效信息有 1 个字节,而不是 4 个字节。因此,我试图找到有关 header 的另一个信息来源,但我只找到了与上述文章中描述的信息相同的信息。

我以为我存储了错误的图像,所以我决定通过 Gimp 打开它并将其存储为 new-one,但看起来 header 具有相同的结构,只是开始图像的移动。

00000000: 424d 2e89 0000 0000 0000 7a04 0000 6c00  BM........z...l.
00000010: 0000 e300 0000 9500 0000 0100 0800 0000  ................
00000020: 0000 b484 0000 130b 0000 130b 0000 0001  ................
00000030: 0000 0001 0000 4247 5273 0000 0000 0000  ......BGRs......
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 0000 0000 0000 0000 0000 0200 0000 0000  ................
00000070: 0000 0000 0000 0000 0000 2c2a 2c00 4c8f  ..........,*,.L.
00000080: 6900 252e 9900 385b 4700 4c54 9700 98c9  i.%...8[G.LT....

因此,不仅 Gimp 可以毫无问题地读取 header,而且它甚至可以创建相同类型的 header。但是根据文档,二进制部分看起来应该存储在 436h 上,相应的 47Ah 上应该使用小端。我显然在那里遗漏了一些东西,但我无法理解这一点,因为不同的来源 fastgraph.com BMP header docs.fileformat.com BMP structure 显示相同的偏移量,但由于某种原因,现实在这里有所不同。你能把我往前推吗?

PS: 我会在这里粘贴原始图像,但看起来图像已自动导出为 png 格式。

感谢大家的回复!

所有回复看来我错了,因为我认为位图调色板的开始是图像的开始,因为开始的颜色看起来像图像第一个像素中的颜色。所有的回复对我都很有用,因为它们帮助我更好地理解了这个话题。在阅读了 Martin Rosenau 的评论后,它帮助我理解了我的错误,这对 http://libertybasicuniversity.com/lbnews/nl100/format.htm 文章也很有帮助。

tl;dr:在你的图像中有一种颜色 table。当有颜色table时,它在DIBheader之后,像素数据在其后。由于颜色 table 从 0x36 运行到 0x435,像素数据本身确实在 0x436.

我上次使用它时,关于 BMP 格式的维基百科文章是正确的,比大多数其他来源更全面、更好。

BMP 文件有一个文件 header,然后是一个位图信息 header(有时称为 DIB header)。像素数据可能会在信息 header 之后立即开始,但可能会有其他颜色信息 and/or 填充。像素数据在那之后。

根据您的第一个十六进制转储,文件 header 表示像素数据从 0x0436 开始,您是正确的。您没有显示足够的文件来查看像素数据是否实际上从 0x0436 开始,但我们可以检查 DIB header 以查看它是否一致。

DIB header比较复杂,因为有很多版本。从偏移量 0x0E 开始,我们可以读取到 DIB header 的大小是 0x28(或十进制的 40)。这告诉我们它是香草 BITMAPINFOHEADER.

位图大小为 227x149 像素。 (当心,因为奇数宽度很难恰到好处。)

像素格式为每像素 8 位,BI_RGB 为压缩值。所以在header之后和像素数据之前会有一个颜色table(调色板)。事实上,header 明确表示将有 256 种颜色 table 条目。

所以颜色 table 从 0x36 开始。颜色 table 中的每个条目都是四个字节(RGBQUAD),因此 table 长度为 256 种颜色 * 4 bytes/color = 1024 字节。因此 table 从 0x36 运行到 0x435.

像素数据可以出现在颜色 table 之后的任何位置,只要它与 4 字节边界对齐即可。因为 0x0436 是 4 的倍数,所以这是第一个可能的可用地址。它也正是文件 header 表示像素数据所在的位置。

(当您使用 Gimp 保存图像时,Gimp 选择使用不同版本的位图信息 header 来保存它,它的长度为 0x6C 字节并且它使用不同的像素格式,因此毫不奇怪像素数据从较大的偏移量开始。)