ad_astra/sprite_generator/main.py
schmelczerandras 26a0fd884f Copy project
2020-04-19 12:48:06 +02:00

110 lines
2.8 KiB
Python

import os
import zipfile
from typing import Tuple
from PIL import Image
import io
from math import ceil
c_header = """#include "sprites.h"
#include <avr/eeprom.h>
// AUTO-GENERATED
"""
h_header = """#ifndef SPRITES_H
#define SPRITES_H
#include <avr/io.h>
// AUTO-GENERATED
"""
h_footer = """
#endif
"""
def generate_content(sprites_directory: str) -> Tuple[str, str]:
output_h = h_header
output_c = c_header
for entry in os.scandir(sprites_directory):
delta_output_h, delta_output_c = process_spritesheet(entry)
output_h += delta_output_h
output_c += delta_output_c
output_h += h_footer
return output_h, output_c
def process_spritesheet(entry) -> Tuple[str, str]:
sprites_name, _ = entry.name.split('.')
sprites_zip = zipfile.ZipFile(entry.path, 'r')
width, height = read_sprite(sprites_zip, sprites_zip.filelist[0]).size
declaration = f'const uint16_t {sprites_name}[{len(sprites_zip.filelist)}][{width}][{ceil(height / 8)}]'
output_h = declaration + ';\n'
output_c = declaration + ' EEMEM = {' + process_sprites(sprites_zip) + '};\n'
return output_h, output_c
def process_sprites(sprites_zip) -> str:
output = ''
width, height = read_sprite(sprites_zip, sprites_zip.filelist[0]).size
for sprite in sprites_zip.filelist:
output += '{'
pixels = list(read_sprite(sprites_zip, sprite).getdata())
for x in range(width):
output += '{'
for y in range(0, height, 8):
fill_bits = ''.join(
reversed([
('1' if is_filled(pixels[(y + i) * width + x]) else '0') if (y + i) * width + x < len(pixels) else '0'
for i in range(8)
])
)
inverted_mask_bits = ''.join(
reversed([
('0' if is_translucent(pixels[(y + i) * width + x]) else '1') if (y + i) * width + x < len(pixels) else '0'
for i in range(8)
])
)
output += f'{binary_to_hex_with_prefix(inverted_mask_bits + fill_bits)},'
output = output[:-1] + '},'
output = output[:-1] + '},'
return output[:-1]
def read_sprite(sprites_zip, entry):
return Image.open(io.BytesIO(sprites_zip.read(entry.filename)))
def is_translucent(pixel: Tuple[int, int, int, int]) -> bool:
r, g, b, a = pixel
return a == 0
def is_filled(pixel: Tuple[int, int, int, int]) -> bool:
r, g, b, a = pixel
return r != 0 or g != 0 or b != 0
def binary_to_hex_with_prefix(binary: str) -> str:
return hex(int(binary, 2))
if __name__ == '__main__':
dot_h, dot_c = generate_content('spritesheets')
with open('output/sprites.h', 'w+') as f:
f.write(dot_h)
with open('output/sprites.c', 'w+') as f:
f.write(dot_c)