0x0006
并且0x0008
是保留的,你应该简单地把零放在那里。至于0x000A
,那是实际图像数据在文件中开始的位置。通常,这里的标头后面是 DIB 标头(从 offset 开始0x000E
),DIB 标头的前四个字节是它的大小。因此,您获取 DIB 标头的大小,添加其起始偏移量 ( 0x000E
),您得到的是实际数据开始的位置 - 将其放在 position 处0x000A
。
以下是来自随机位图文件的示例数据:
42 4D "BM"
2E 78 08 00 Size of the entire bitmap file (0x8782E meaning 555054 bytes)
00 00 creator1, reserved
00 00 creator2, reserved
36 00 00 00 Image data starts at offset 0x36 because the next 0x28 bytes are DIB header
28 00 00 00 DIB header started and its size is 0x28 (40 bytes)
another 36 bytes
FF FF FF First pixel of the image (white as it happens)
如果您以serverfault.com 上的 favicon为例,您将获取文件中位于 offset0x0016
和之间的部分,0x013E
并在其前面加上 with 42 4D 36 01 00 00 00 00 00 00 36 00 00 00
。这为您提供了一种正确的位图文件 - IrfanView 甚至会显示它。但是,ICO 文件和 BMP 文件中存储的数据并不完全相同,因为 ICO 文件需要存储透明度信息。这就是为什么这个网站图标根据其 DIB 标头的大小为 16x32,而不是预期的 16x16。
来自维基百科:
颜色深度小于 32 位的图像遵循特定格式:图像被编码为由颜色掩码(“XOR 掩码”)和不透明掩码(“AND 掩码”)组成的单个图像。XOR 掩码必须在位图数据内的 AND 掩码之前;如果图像以自下而上的顺序存储(很可能是这样),则 XOR 掩码将绘制在 AND 掩码下方。
在我们的特殊情况下,这意味着从 256 个字节的图像数据中,前 64 个字节是 XOR 掩码,最后 64 个字节是 AND 掩码,只有中间部分是我们的图像。在我们的特殊情况下,您可以将图像数据的开始(偏移量0x000A
)更改为 0x76 以跳过 XOR 掩码。然后,您还将 DIB 标头(偏移量0x0016
)中的图像高度更改为 0x10,以确保忽略 AND 掩码。在这里,这些操作将为您提供一个有效的位图,与您的预期非常相似。在一般情况下,最好考虑掩码而不是忽略它们。