pt2game/compress_sprite.py

60 lines
2.0 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/python3
import sys
import struct
import PIL.Image
_, inpath, outpath = sys.argv
image = PIL.Image.open(inpath)
assert image.mode == "RGBA", "image mode is "+image.mode
# We measure width and height prior to the rotation
width, height = image.width, image.height
image = image.transpose(PIL.Image.Transpose.ROTATE_270)
with open(outpath, "wb") as out:
out.write(struct.pack("=HH", width, height))
for channel in "BGRA":
pixelbytes = image.getchannel(channel).tobytes()
def rlegroups():
curpixel=None
count=0
litrun = b""
for pixel in pixelbytes:
if curpixel is None:
curpixel = pixel
count = 1
elif curpixel != pixel:
assert count > 0
if count <= 2:
if len(litrun)+count > 127:
assert len(litrun) > 0
yield litrun
litrun = b""
litrun += bytes([curpixel]) * count
else:
if litrun != b"":
assert len(litrun) > 0
yield litrun
litrun = b""
yield (curpixel, count)
curpixel = pixel
count = 1
else:
count += 1
if litrun != b"":
assert len(litrun) > 0
yield litrun
if count > 0:
yield (curpixel, count)
for group in rlegroups():
if type(group) == bytes:
out.write(struct.pack("=B", len(group)+128) + group)
else:
pixel, count = group
assert count > 0
if count >= 128:
out.write(struct.pack("=BIB", 0, count, pixel))
else:
out.write(struct.pack("=BB", count, pixel))