这是我的 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。
我也试过给“pixel”中的颜色添加透明通道,但还是不行。
我用Windows系统的“画图工具”创建了一个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
您需要阅读PNG格式规范。整个东西。不要只是浏览它。
每一行像素前面都有一个过滤字节。零表示没有过滤。所以你的像素需要:
pixel = zlib.compress(b'\x00\xff\x00\x00\x00\xff\x00\x00\x00\x00\xff\x80\x80\x80')