Initial WhaleTown V2 backend
This commit is contained in:
82
scripts/skin_generation/tools/save_single_row_review.py
Normal file
82
scripts/skin_generation/tools/save_single_row_review.py
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user