Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
#!/usr/bin/env python3
from PIL import Image
import argparse
def bytes_from_bitstream_le(bitstream):
accum = 0
accum_size = 0
while True:
while accum_size < 8:
nbits, newdata = next(bitstream)
accum = accum | (newdata << accum_size)
accum_size += nbits
while accum_size >= 8:
yield accum & 0xff
accum = accum >> 8
accum_size -= 8
def format_pixel(format, src_has_transparency, pixel):
assert(format in ["argb1555", "argb1232", "p8", "p4", "p2", "p1"])
if format == "argb1555":
return (16, ((pixel[2] & 0xf8) >> 3) | \
((pixel[1] & 0xf8) << 2) | \
((pixel[0] & 0xf8) << 7) | \
(((pixel[3] & 0x80) << 8) if len(pixel) > 3 and src_has_transparency else 0x8000))
elif format == "argb1232":
return (8, ((pixel[2] & 0xc0) >> 6) |\
((pixel[1] & 0xe0) >> 3) | \
((pixel[0] & 0xc0) >> 1) | \
(pixel[3] & 0x80 if len(pixel) > 3 and src_has_transparency else 0x80))
elif format in ["p8", "p4", "p2", "p1"]:
size = int(format[1:])
return (size, (pixel + src_has_transparency) & ((1 << size) - 1))
else:
raise Exception()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("input", help="Input file name")
parser.add_argument("output", help="Output file name")
parser.add_argument("--tilesize", "-t", help="Tile size (pixels), default 8",
default="8", choices=["8", "16"])
parser.add_argument("--format", "-f", help="Output pixel format, default argb1555",
default="argb1555", choices=["argb1555", "argb1232", "p8", "p4", "p2", "p1"])
args = parser.parse_args()
img = Image.open(args.input)
ofile = open(args.output, "wb")
tilesize = int(args.tilesize)
format_is_paletted = args.format.startswith("p")
image_is_transparent = img.mode == "RGBA" and img.getextrema()[3][0] < 255
if format_is_paletted:
ncolours_max = 1 << int(args.format[1:])
ncolours_actual = min(ncolours_max, len(img.getcolors()))
pimg = img.quantize(ncolours_max)
palette = pimg.getpalette()
# TODO haven't found a sane way to make PIL map transparency to palette
if image_is_transparent:
for x in range(img.width):
for y in range(img.height):
if not (img.getpixel((x, y))[3] & 0x80):
pimg.putpixel((x, y), 255)
with open(args.output + ".pal", "wb") as pfile:
if image_is_transparent:
pfile.write(bytes(2))
pfile.write(bytes(bytes_from_bitstream_le(
format_pixel("argb1555", False, palette[i:i+3]) for i in range(0, ncolours_actual * 3, 3)
)))
img = pimg
for y in range(0, img.height - (tilesize - 1), tilesize):
for x in range(0, img.width - (tilesize - 1), tilesize):
tile = img.crop((x, y, x + tilesize, y + tilesize))
ofile.write(bytes(bytes_from_bitstream_le(
format_pixel(args.format, image_is_transparent, tile.getpixel((i, j))) for j in range(tilesize) for i in range(tilesize)
)))
165036038This file is pinned to the selected release. Download the original to open it in your design tool.