尝试从给定的 PNG 图像中提取像素值
Posted
技术标签:
【中文标题】尝试从给定的 PNG 图像中提取像素值【英文标题】:Trying to extract pixel values from a given PNG image 【发布时间】:2012-06-21 10:20:56 【问题描述】:尝试理解 PNG 格式。
考虑一下这个 PNG 图片:
图片取自here
在十六进制编辑器中,它看起来像这样:
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 80 00 00 00 44 08 02 00 00 00
C6 25 AA 3E 00 00 00 C2 49 44 41 54 78 5E ED D4 81 06 C3 30 14 40 D1 B7 34 DD FF FF 6F
B3 74 56 EA 89 12 6C 28 73 E2 AA 34 49 03 87 D6 FE D8 7B 89 BB 52 8D 3B 87 FE 01 00 80
00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40
00 00 08 00 00 01 00 20 00 00 00 D4 5E 6A 64 4B 94 F5 98 7C D1 F4 92 5C 5C 3E CF 9C 3F
73 71 58 5F AF 8B 79 5B EE 96 B6 47 EB F1 EA D1 CE B6 E3 75 3B E6 B9 95 8D C7 CE 03 39
C9 AF C6 33 93 7B 66 37 CF AB BF F9 C9 2F 08 80 00 00 10 00 00 02 00 40 00 00 08 00 00
01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 8C 37 DB
68 03 20 FB ED 96 65 00 00 00 00 49 45 4E 44 AE 42 60 82
等价字符:
‰PNG........IHDR...€...D.....Æ%ª>...ÂIDATx^íÔ..Ã0.@Ñ·4Ýÿÿo³tVê‰.l(sâª4I.‡Öþ؉
»R.;‡þ..€.......@....... ....€.......@....... ...Ô^jdK”õ˜|Ñô’\\>Ïœ?sqX_¯
‹y[î–¶GëñêÑζãu;湕.ÇÎ.9ɯÆ3“f7Ï«¿ùÉ/.€.......@....... ....€.......@....... ..Œ7Ûh.
ûí–e....IEND®B`‚
HEX 编辑器截图如下:
我正在尝试对该图像进行逆向工程以提取标题部分和 RGB 像素值。我读到了 PNG 和 here ,到目前为止,我已经注意到关于这张图片的以下内容:
IHDR 块必须首先出现。它包含:
Width: 4 bytes
Height: 4 bytes
Bit depth: 1 byte
Color type: 1 byte
Compression method: 1 byte
Filter method: 1 byte
Interlace method: 1 byte
下面我开始依次读取 HEX 数据:
1- 前 8 字节:这是 8 字节签名
89 50 4E 47 0D 0A 1A 0A
相当于:%PNG 可以在 HEX 编辑器中看到
有效的 PNG 图像必须包含一个 IHDR 块、一个或多个 IDAT 块和一个 IEND 块。
2- 块:长度
00 00 00 0D
3-Chunk:块类型
49 48 44 52
什么是 IHDR。
http://www.w3.org/TR/PNG-Chunks.html
4- 块:图像的宽度(十进制 128)
00 00 00 80
5- Chunk:图片高度(68 进制)
00 00 00 44
6- 块:位深度(1 字节)
08
7- 块:颜色类型
02
8-压缩方式
00
9-过滤方法:
00
10-交错法:
00
11- 以下数据是什么?
C6 25 AA 3E 00 00 00 C2
12-- IDAT
49 44 41 54
13- 这是什么数据(IDAT 之后):
78 5E ED D4 81 06 C3 30 14 40 D1 B7 34 DD FF FF 6F B3 74 56 EA 89 12 6C 28 73 E2 AA 34 49 03 87 D6 FE D8 7B 89 BB 52 8D 3B 87 FE 01 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 4 4 D4 4 5E F 59 8 B 6 D4 4 5E F 6A 92 5C 5C 3E CF 9C 3F 73 71 58 5F AF 8B 79 5B EE 96 B6 47 EB F1 EA D1 CE B6 E3 75 3B E6 B9 95 8D C7 CE 03 39 C9 AF C6 33 93 7B 66 37 CF AB BF F9 C9 2F 08 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 7 6 00 03 2C 00 00 00 01 00 20 7 6 00 03 2C 0 65 00 00 00 00
14- IEND:
49 45 4E 44
15- 最后 4 个字节
AE 42 60 82
这些是什么?
上面的第 11、13 和 15 点可以帮助我理解吗?像素值在哪里?图像具有(128 x 68 像素)
了解这些细节的目的:
一旦我知道了这些细节,我将生成自己的 16 位 PNG 图像。我已经有了像素值,所以我的工作是引入标题等。 我不知道是否有软件可以完成这项工作。
更新
我现在明白了,因为压缩,我无法定位像素值。
我想到我可以在 OpenCV 中编写一个文件并将其保存为 png。那么现在我的直接问题是:我有一个具有灰度 16 位像素值的 binary 文件。我可以在 OpenCV 中将其写为 16 位 PNG 吗?
【问题讨论】:
【参考方案1】:虽然了解 PNG 图像实际上是什么以及图像在文件中的实际表示方式可能很有趣,但您无需知道这些即可生成 PNG 文件。
请注意,PNG 使用无损压缩,这意味着每个像素不会得到两个字节。
您可以使用现有的许多库在程序中生成图像并以 PNG 格式输出。
例如,您可以在 OpenCV 中制作图像,然后使用imWrite
将其输出。其中一个参数可以使其输出为PNG。
如果你有灰度 16 位像素值,那么你可以把它们放到一个Mat
中。
然后将其转换为 IplImage:Converting cv::Mat to IplImage*
然后就可以输出到文件了。
【讨论】:
我刚刚注意到压缩,所以它很好我不会得到精确的像素值。但是你能告诉我关于 11 和 15 的事情吗? 谢谢,您的回答对我很有帮助。我会测试它,然后发布结果。 +1 但我不完全同意“你只是在浪费时间”。对于您当前的任务,可能不需要了解 PNG 的内部结构,但它仍然在学习。 伙计们,今天我已经了解了 PNG 的内部和外部!谢谢你们的帮助!是的,学习底层细节很重要,因为它可以让事情成为未来的证明。 好吧,你说得对。我的发言相当激进。【参考方案2】:只是为了完整(eboix的回答当场就对了)
11- 以下数据是什么?
C6 25 AA 3E 00 00 00 C2
每个块都以CRC(4 个字节)结尾,并以 4 个字节表示其长度。
所以,C6 25 AA 3E
是前一个块 (IHDR) 的 CRC,00 00 00 C2
(194) 是后面 (IDAT) 块的长度。
同理,最后4个字节是IEND块的CRC。
【讨论】:
【参考方案3】:我没有仔细看,而是从结构上看...
Q11。 C6 25 AA 3E = CRC32 00 00 00 C2 = 下一个块的大小
Q13。 检查你之前提到的 png 规范,它看起来像你已经知道应用到它的压缩的 IDAT 块!
Q15。 AE 42 60 82 = CRC32
【讨论】:
以上是关于尝试从给定的 PNG 图像中提取像素值的主要内容,如果未能解决你的问题,请参考以下文章