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()