83 lines
3.2 KiB
Python
83 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Save single-row review images from an assembled WhaleTown spritesheet."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
|
|
def checkerboard(width: int, height: int, tile: int) -> Image.Image:
|
|
image = Image.new("RGBA", (width, height), (226, 226, 226, 255))
|
|
draw = ImageDraw.Draw(image)
|
|
for y in range(0, height, tile):
|
|
for x in range(0, width, tile):
|
|
if (x // tile + y // tile) % 2 == 0:
|
|
draw.rectangle((x, y, x + tile - 1, y + tile - 1), fill=(248, 248, 248, 255))
|
|
return image
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--sheet", type=Path, required=True)
|
|
parser.add_argument("--direction", default="down")
|
|
parser.add_argument("--row", type=int, default=0)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
parser.add_argument("--feet-output", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
|
|
frame_size = 160
|
|
columns = 8
|
|
row = Image.open(args.sheet).convert("RGBA").crop(
|
|
(0, args.row * frame_size, columns * frame_size, (args.row + 1) * frame_size)
|
|
)
|
|
font = ImageFont.load_default()
|
|
|
|
scale = 2
|
|
label_width = 68
|
|
preview = row.resize((row.width * scale, row.height * scale), Image.Resampling.NEAREST)
|
|
canvas = Image.new("RGB", (label_width + preview.width, preview.height), (246, 247, 250))
|
|
plate = checkerboard(preview.width, preview.height, 16)
|
|
plate.alpha_composite(preview)
|
|
canvas.paste(plate.convert("RGB"), (label_width, 0))
|
|
draw = ImageDraw.Draw(canvas)
|
|
draw.text((8, preview.height // 2 - 5), args.direction, fill=(28, 32, 36), font=font)
|
|
for index in range(columns + 1):
|
|
x = label_width + index * frame_size * scale
|
|
draw.line((x, 0, x, preview.height), fill=(205, 60, 60), width=1)
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
canvas.save(args.output)
|
|
|
|
feet_y = round(frame_size * 0.49)
|
|
feet_scale = 4
|
|
feet_height = frame_size - feet_y
|
|
cell_width = frame_size * feet_scale
|
|
cell_height = feet_height * feet_scale
|
|
label_height = 22
|
|
feet_canvas = Image.new(
|
|
"RGB", (label_width + columns * cell_width, label_height + cell_height), (246, 247, 250)
|
|
)
|
|
feet_draw = ImageDraw.Draw(feet_canvas)
|
|
feet_draw.text((7, label_height + cell_height // 2 - 5), args.direction, fill=(28, 32, 36), font=font)
|
|
for index in range(columns):
|
|
feet_draw.text((label_width + index * cell_width + 4, 5), f"F{index + 1}", fill=(72, 76, 82), font=font)
|
|
cell = row.crop((index * frame_size, feet_y, (index + 1) * frame_size, frame_size)).resize(
|
|
(cell_width, cell_height), Image.Resampling.NEAREST
|
|
)
|
|
plate = checkerboard(cell_width, cell_height, 20)
|
|
plate.alpha_composite(cell)
|
|
x = label_width + index * cell_width
|
|
feet_canvas.paste(plate.convert("RGB"), (x, label_height))
|
|
feet_draw.rectangle(
|
|
(x, label_height, x + cell_width - 1, label_height + cell_height - 1),
|
|
outline=(188, 194, 202),
|
|
width=1,
|
|
)
|
|
feet_canvas.save(args.feet_output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|