Language agnostic 如何从ICO文件中提取BMP?

Language agnostic 如何从ICO文件中提取BMP?,language-agnostic,ico,file-structure,Language Agnostic,Ico,File Structure,我正在做一些工作,以编程方式从OpenSearch文档中指定的站点下载图标,如果第一个图像是ICO格式的,我需要提取第一个图像(目前)。我能够毫无问题地读取ICO文件头并切掉第一个图像文件。然而,在阅读之后,我发现,如果图像是位图格式,那么文件是不完整的(缺少标题)。因此,在将数据保存到文件之前,我需要重建这个头文件,但是我有点困难 根据,标头的长度为14字节,应包含以下内容: Offset Data 0x0000 "BM", for our intents and purposes

我正在做一些工作,以编程方式从OpenSearch文档中指定的站点下载图标,如果第一个图像是ICO格式的,我需要提取第一个图像(目前)。我能够毫无问题地读取ICO文件头并切掉第一个图像文件。然而,在阅读之后,我发现,如果图像是位图格式,那么文件是不完整的(缺少标题)。因此,在将数据保存到文件之前,我需要重建这个头文件,但是我有点困难

根据,标头的长度为14字节,应包含以下内容:

Offset Data
0x0000
"BM", for our intents and purposes
0x0002
Size of the bitmap file in bytes
0x0006
Dependant on the application creating the file
0x0008
Dependant on the application creating the file
0x000A
Offset of the image data/pixel array 我估计位图文件的大小(以字节为单位)将是提取图像的大小+头的14个字节,但我不确定在0x0006、0x0008处写入什么,以及如何获取要在0x000A处写入的像素阵列的位置


这篇文章我读了好几遍,但我必须承认我的头有点痛。这是我做这类事情的第一次经验。有人能帮我找到像素阵列的位置吗?

0x0006
0x0008
都是保留的,你只需在那里加上零即可。对于
0x000A
,这是文件中实际图像数据开始的位置。通常情况下,这里的头后面跟着DIB头(从偏移量
0x000E
开始),DIB头的前四个字节是它的大小。因此,取DIB标题的大小,添加其起始偏移量(
0x000E
),得到的是实际数据起始的位置-将其放在位置
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)
如果以为例,您将获取偏移量
0x0016
0x013E
之间的文件部分,并使用
42 4D 36 01 00 00 36 00 00
将其前置。这将为您提供一种正确的位图文件,IrfanView甚至会显示它。但是,ICO文件和BMP文件中存储的数据并不完全相同,因为ICO文件需要存储透明度信息。这就是为什么这个favicon根据其DIB头的大小为16x32,而不是预期的16x16

发件人:

颜色深度小于32位的图像遵循特定格式:图像编码为单个图像,由颜色遮罩(“XOR遮罩”)和不透明度遮罩(“AND遮罩”)组成。XOR掩码必须位于位图数据中的AND掩码之前;如果图像以自底向上的顺序存储(很可能是这样),那么XOR掩码将绘制在AND掩码下面


在我们的特殊情况下,这意味着从256字节的图像数据中,前64字节是XOR掩码,后64字节是和掩码,只有中间部分是我们的图像。在我们的特殊情况下,您可以将图像数据的开始(偏移量
0x000A
)更改为0x76以跳过异或掩码。然后还可以将DIB标题中的图像高度(偏移量
0x0016
)更改为0x10,以确保忽略和掩码。在这里,这些操作将为您提供一个有效的位图,与您所期望的非常相似。一般情况下,最好是考虑掩码,而不是忽略它们。

这对我不起作用。我在看电视。如果我提取图像数据,从图标目录中的偏移量到偏移量+大小。然后,我按照0x000A处的36重建位图标题,将整个内容保存为bmp文件,并尝试在windows中加载结果。我收到一个错误,说文件已损坏或太大。Wikipedia提示,像素值从颜色表和可选的1字节间距之后开始。是吗?@Andy:那是因为ICO文件中的数据不是“常规”位图数据。看我答案的更新版本。啊,我现在明白了。我不能只是把位图拉出来,期望Windows显示它。我必须将图像重建为PNG或其他格式。谢谢你的帮助。