Under writing.
import zlib, binascii
from struct import pack, unpack
class PNGColorType():
GRAYSCALE = 0
RGB = 2
PLTE = 3
GRAYSCALE_A = 4
RGBA = 6
class PNGCompression():
NO_COMPRESSION = 0
class PNGFilter():
NO_FILTER = 0
class PNGInterlace():
NO_INTERLACE = 0
class PNG():
SIGNATURE = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
def __init__(self, width, height, bpp, _color = PNGColorType.GRAYSCALE, _compression = PNGCompression.NO_COMPRESSION, _filter = PNGFilter.NO_FILTER, _interlace = PNGInterlace.NO_INTERLACE ):
self.width = width
self.height = height
self.bpp = bpp
self.color = _color
self.compression = _compression
self.filter = _filter
self.interlace = _interlace
def get_signature(self):
return pack('>{}B'.format( len(PNG.SIGNATURE) ), *PNG.SIGNATURE)
def get_ihdr(self):
TYPE = b'IHDR' # CHUNK TYPE
DATA = pack('>IIBBBBB',
self.width & 0xFFFFFFFF, # WIDTH
self.height & 0xFFFFFFFF, # HEIGHT
self.bpp & 0xFF, # BPP
self.color & 0xFF, # COLOR TYPE
self.compression & 0xFF, # COMPRESSION
self.filter & 0xFF, # FILTER
self.interlace & 0xFF # INTERLACE
)
LENGTH = len(DATA) # LENGTH
CRC = binascii.crc32(
TYPE + DATA
)
return pack('>I4s', LENGTH, TYPE) + DATA + pack('>i', CRC)
def create_idat(self, data):
if not isinstance(data, list) and not isinstance(data, tuple):
data = [data]
TYPE = b'IDAT' # CHUNK TYPE
raw = b"\0" # no filter for this scanline
for d in data:
raw += pack('>H', d)
compressor = zlib.compressobj()
DATA = compressor.compress(raw)
DATA += compressor.flush()
LENGTH = len(DATA) # LENGTH
CRC = binascii.crc32(
TYPE + DATA
)
return pack('>I4s', LENGTH, TYPE) + DATA + pack('>i', CRC)
def get_iend(self):
TYPE = b'IEND' # CHUNK TYPE
LENGTH = 0 # LENGTH
return pack('>I4si', LENGTH, TYPE, binascii.crc32(TYPE))
def main():
x = 10
y = 10
test = PNG(x, y, 16, PNGColorType.RGB, PNGCompression.NO_COMPRESSION, PNGFilter.NO_FILTER, PNGInterlace.NO_INTERLACE)
RED = 0xF000
GREEN = 0x0F00
BLUE = 0x000F
WHITE = 0xFFFF
BLACK = 0x000F
with open('toast.png', 'wb') as f:
f.write( test.get_signature() )
f.write( test.get_ihdr() )
for i in range(10):
f.write( test.create_idat( (RED, BLUE) ) )
f.write( test.get_iend() )
main()