pokemon/tools/png_to_nbpp_sprite.py

69 lines
1.9 KiB
Python

import os
import sys
from PIL import Image
from palette import intensity_to_index
cell_width = 16
cell_height = 16
def convert(image, bpp):
assert bpp in {8, 4, 2}, bpp
bits_per_byte = 8
px_per_byte = bits_per_byte // bpp
px_per_row = cell_width
bytes_per_row = (px_per_row // px_per_byte)
assert image.mode == 'L', image.mode
width, height = image.size
buf = bytearray(width * height // px_per_byte)
for cell_y in range(height//cell_height):
cell_y_start = cell_y * bytes_per_row * cell_height
for cell_x in range(width//cell_width):
cell_x_start = cell_y_start + bytes_per_row * cell_x
for y in range(cell_height):
for x in range(cell_width):
px = im.getpixel((cell_x * cell_width + x, cell_y * cell_height + y))
index = intensity_to_index(px)
buf_ix = cell_x_start + x//px_per_byte + y * bytes_per_row
buf[buf_ix] |= (index << bpp * ((px_per_byte - 1) - (x % px_per_byte)))
return buf
# (pixels/row)
# ------------ *
# (pixels/byte)
def debug(buf, bpp):
assert bpp in {8, 4, 2}, bpp
bits_per_byte = 8
px_per_byte = bits_per_byte // bpp
px_per_row = cell_width
bytes_per_row = (px_per_row // px_per_byte)
bit_mask = (2 ** bpp) - 1
for row in range(len(buf) // bytes_per_row):
for x in range(bytes_per_row):
px = buf[row * bytes_per_row + x]
for shift in reversed(range(px_per_byte)):
print((px >> (shift * bpp)) & bit_mask, end='')
print()
if (row % cell_height == (cell_height - 1)):
print()
in_path = sys.argv[1]
bpp = int(sys.argv[2])
out_path = sys.argv[3]
im = Image.open(in_path)
buf = convert(im, bpp)
if 'NBPP_DEBUG' in os.environ:
debug(buf, bpp)
with open(out_path, 'wb') as f:
f.write(buf)