python PNG图像的IDAT块如何存储像素信息?

ruoxqz4g  于 2023-03-28  发布在  Python
关注(0)|答案(1)|浏览(229)

这是我的Python代码:

import struct
import zlib

PNG_HEADER = b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a'
IHDR = b'\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x02\x00\x00\x00\x02\x08\x02\x00\x00\x00'
IHDR += struct.pack('>I', zlib.crc32(IHDR[4:]))
sRGB = b'\x00\x00\x00\x01\x73\x52\x47\x42\x00\xAE\xCE\x1C\xE9'
pixel = zlib.compress(b'\xff\x00\x00\x00\xff\x00\x00\x00\xff\x80\x80\x80')
IDAT = struct.pack('>I', len(pixel)) + b'IDAT' + pixel
IDAT += struct.pack('>I', zlib.crc32(IDAT[4:]))
PNG_END = b'\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82'

file = PNG_HEADER + IHDR + sRGB + IDAT + PNG_END

with open('test.png', 'wb') as f:
    f.write(file)

PNG图片:

代码中的像素表示为没有透明通道的RGB通道,但实际生成的图像不是“像素”中设置的颜色。
我试着将“颜色类型”从02改为04或06,但我仍然无法实现“像素”中的颜色。
还尝试将图像深度从08更改为10。
我还尝试在“像素”中为颜色添加透明通道,但仍然不起作用。
我使用Windows系统的“Paint tool”创建了一个8x5的PNG图像,并使用zlib解压缩IDAT块中的数据,但我发现我根本无法理解。
所以现在我想知道IDAT块中的像素信息是如何存储的,我去libpng的官网查询了一下,但是查不到具体的信息。
我查阅了很多文档,但仍然不明白如何存储IDAT块。
例如,什么情况下它有四个通道(RGBA)?什么情况下你只有三个通道(RGB)?以及图像“位深”和“颜色类型”会给图像带来什么变化?
例如,如果我手动将“图像位深”更改为08,将“颜色类型”更改为06,那么我可能可以使用RGBA的四个通道,但不会显示下一行像素,例如:

IHDR:
width:      00 00 00 02
height:     00 00 00 02
bit depth:  08
color type: 06

Pixel information I manually wrote (uncompressed data):
background color?  00
First pixel:       ff 00 00 ff
Second pixel:      00 ff 00 ff
Third pixel:       00 00 ff ff
Fourth pixel:      ff 00 ff ff

The third and fourth pixels will not be visible using the image viewer, but will only see a white background.

以下是我所指的网页的连结:

https://www.w3.org/TR/png/
https://zh.wikipedia.org/wiki/PNG
http://www.libpng.org/pub/png/book/chapter11.html
http://www.libpng.org/pub/png/book/chapter08.html
http://www.libpng.org/pub/png/book/toc.html
http://www.libpng.org/pub/png/spec/1.2/png-1.2.pdf
http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
http://libpng.org/pub/png/
https://www.sciencedirect.com/science/article/pii/S174228761930163X
https://www.youtube.com/watch?v=BLnOD1qC-Vo&ab_channel=sandalaz
https://www.codeproject.com/Articles/581298/PNG-Image-Steganography-with-libpng
https://www.cnblogs.com/flylong0204/articles/4955235.html
https://www.cnblogs.com/senior-engineer/p/9548347.html
https://www.cnblogs.com/ECJTUACM-873284962/p/8986391.html
https://www.nayuki.io/page/png-file-chunk-inspector
tjvv9vkg

tjvv9vkg1#

你得把PNG format specification都看一遍,不要只看一眼。
每一行像素前面都有一个过滤字节。零表示没有过滤。所以你的像素需要:

pixel = zlib.compress(b'\x00\xff\x00\x00\x00\xff\x00\x00\x00\x00\xff\x80\x80\x80')

相关问题