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

问题描述 投票:0回答:1

这是我的 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
python image image-processing png libpng
1个回答
0
投票

您需要阅读PNG格式规范。整个东西。不要只是浏览它。

每一行像素前面都有一个过滤字节。零表示没有过滤。所以你的像素需要:

pixel = zlib.compress(b'\x00\xff\x00\x00\x00\xff\x00\x00\x00\x00\xff\x80\x80\x80')
© www.soinside.com 2019 - 2024. All rights reserved.