|
import struct |
|
import zlib |
|
|
|
def encode(buf, width, height): |
|
""" buf: must be bytes or a bytearray in py3, a regular string in py2. formatted RGBRGB... """ |
|
assert (width * height * 3 == len(buf)) |
|
bpp = 3 |
|
|
|
def raw_data(): |
|
|
|
row_bytes = width * bpp |
|
for row_start in range((height - 1) * width * bpp, -1, -row_bytes): |
|
yield b'\x00' |
|
yield buf[row_start:row_start + row_bytes] |
|
|
|
def chunk(tag, data): |
|
return [ |
|
struct.pack("!I", len(data)), |
|
tag, |
|
data, |
|
struct.pack("!I", 0xFFFFFFFF & zlib.crc32(data, zlib.crc32(tag))) |
|
] |
|
|
|
SIGNATURE = b'\x89PNG\r\n\x1a\n' |
|
COLOR_TYPE_RGB = 2 |
|
COLOR_TYPE_RGBA = 6 |
|
bit_depth = 8 |
|
return b''.join( |
|
[ SIGNATURE ] + |
|
chunk(b'IHDR', struct.pack("!2I5B", width, height, bit_depth, COLOR_TYPE_RGB, 0, 0, 0)) + |
|
chunk(b'IDAT', zlib.compress(b''.join(raw_data()), 9)) + |
|
chunk(b'IEND', b'') |
|
) |
|
|