my PNG 10x10 picture for the test
Hi everybody, I try to make a Python script that reads/writes a PNG file. I don't need a full option script. In this test, no compression, no filter, no interlace, I use a RGB palette and an Alpha palette (Color Type 3) with a 8 Bit Depth.
I simply don't understand the IDAT chunk... I was expecting a list of index colors like: 10px Width x 10px Height x 8 Bit Depth -> 100 Bytes of data in the IDAT but instead I have 206 Bytes. (Please correct me if I'm wrong) And a range of 0 to 66 for the index colors but it's completely out of range.
If someone can explain me how I'm supposed to read this data or what i did wrong, I'll appreciate it.
this is my code (line 50 for the IDAT):
#!/usr/bin/env python3
with open("smile.png", 'rb') as f:
hexData = f.read().hex()
#Init cursor_0
cursor_0 = 0
#check signature (8 bytes)
start = cursor_0
stop = cursor_0+(8*2)
cursor_0 = stop
if hexData[start:stop] != "89504e470d0a1a0a":
print("signature fail")
#Read each Chunk
read = True
while read:
#NEW CHUNK
#read length of the chunk (4 bytes)
start = cursor_0
stop = cursor_0+(4*2)
cursor_0 = stop
chunkDataLength = int(hexData[start:stop],16)
#read type of the chunk (4 bytes)
start = cursor_0
stop = cursor_0+(4*2)
cursor_0 = stop
chunkTypeHex = hexData[start:stop]
chunkType = bytes.fromhex(hexData[start:stop]).decode()
#read the data of the chunk (variable)
start = cursor_0
stop = cursor_0+(chunkDataLength*2)
cursor_0 = stop
chunkDataHex = hexData[start:stop]
#read the CRC of the chunk (4 bytes)
start = cursor_0
stop = cursor_0+(4*2)
cursor_0 = stop
chunkCrcHex = hexData[start:stop]
#Decode
#Init cursor_1
cursor_1 = 0
if chunkType == "IHDR":
print(chunkType)
#check the pDataLength
if chunkDataLength != 13:
print("unexpected pDataLength: "+ chunkDataLength)
#Width (4 bytes)
start = cursor_1
stop = cursor_1+(4*2)
cursor_1 = stop
width = int(chunkDataHex[start:stop])
print("Width: "+str(width))
#Height (4 bytes)
start = cursor_1
stop = cursor_1+(4*2)
cursor_1 = stop
height = int(chunkDataHex[start:stop])
print("Height: "+str(height))
#Bit Depth (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
bitDepth = int(chunkDataHex[start:stop])
print("Bit Depth: "+str(bitDepth))
#Color Type (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
colorType = int(chunkDataHex[start:stop])
print("ColorType: "+str(colorType))
#Compression Method (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
compressionMethod = int(chunkDataHex[start:stop])
print("Compression Method: "+str(compressionMethod))
#Filter Method (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
filterMethod = int(chunkDataHex[start:stop])
print("Filter Method: "+str(filterMethod))
#Interlace Method (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
interlaceMethod = int(chunkDataHex[start:stop])
print("Interlace Method: "+str(interlaceMethod))
elif chunkType == "PLTE":
print(chunkType)
print(str(int(chunkDataLength/3)) + " Colors")
while cursor_1 < chunkDataLength*2:
#RED (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
red = chunkDataHex[start:stop]
#GREEN (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
green = chunkDataHex[start:stop]
#BLUE (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
blue = chunkDataHex[start:stop]
color = red+green+blue
#print("Color: "+ color)
elif chunkType == "tRNS":
print(chunkType)
print(str(int(chunkDataLength)) + " Transparent Colors")
while cursor_1 < chunkDataLength*2:
#Transparent Color (1 byte)
start = cursor_1
stop = cursor_1+(1*2)
cursor_1 = stop
transparent = chunkDataHex[start:stop]
#print("Transparent Color: "+ transparent)
elif chunkType == "IDAT":
print(chunkType)
#>>>1ST TRY
while cursor_1 < chunkDataLength*bitDepth/8*2:
start = int(cursor_1)
stop = int(cursor_1 + bitDepth/8*2)
cursor_1 = stop
colorIndex = int(chunkDataHex[start:stop],16)
print("ColorIndex: "+str(colorIndex))
#>>>2ND TRY
#translate Hexadecimal to Binary
chunkDataBin = bin(int(chunkDataHex,16))
#print("len(chunkDataBin)/8="+str(len(chunkDataBin)/8))
#print("chunkDataLength="+str(chunkDataLength))
#start at 2 for jumping the 0b prefixe
cursor_1 = 2
while cursor_1 < chunkDataLength*bitDepth:
start = cursor_1
stop = cursor_1 + bitDepth
cursor_1 = stop
colorIndex = int(chunkDataBin[start:stop],2)
#print("ColorIndex: "+str(colorIndex))
elif chunkType == "IEND":
print(chunkType)
#If END OF FILE detected, break the loop
read = False
else:
print("PyPng script can't handle " + chunkType + " chunk type")