This is my Python code:
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)
This is PNG image:
The pixels in the code are represented as RGB channels without transparent channels, but the actual generated image is not the color set in the "pixel".
I tried to change the "color type" from 02 to 04 or 06, but I still couldn't achieve the colors in the 'pixel'.
An attempt was also made to change the image depth from 08 to 10.
I also tried adding transparent channels to the colors in "pixel", but it still didn't work.
I used the Windows system's "Paint tool" to create an 8x5 PNG image and decompress the data in the IDAT block using zlib, but I found that I simply couldn't understand.
So now I want to know how the pixel information in the IDAT block is stored. I went to the official website of libpng, but I couldn't find the specific information.
I have consulted many documents, but I still cannot understand how to store IDAT blocks.
For example, under what circumstances does it have four channels (RGBA)? Under what circumstances do you only have three channels (RGB)? And what changes will image "bit depth" and "color type" bring to the image?
For example, if I manually change the "image bit depth" to 08 and the "color type" to 06, then I may be able to use the four channels of RGBA, but the next row of pixels will not be displayed, such as:
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.
The following is a link to the webpage I have referred to:
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
You need to read the PNG format specification. The whole thing. Don't just skim it.
Every row of pixels is preceded by a filter byte. A zero means no filtering. So your pixels need to be:
pixel = zlib.compress(b'\x00\xff\x00\x00\x00\xff\x00\x00\x00\x00\xff\x80\x80\x80')