62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
DEFAULT_SOURCE_DIR = ROOT / "tmp" / "imagegen"
|
|
OUTPUT_ROOT = ROOT / "src" / "assets" / "images" / "ui" / "equipment-icons"
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(
|
|
description="Build centered 128px and 32px equipment icons from transparent source art."
|
|
)
|
|
parser.add_argument("ids", nargs="+", help="Equipment ids whose <id>-alpha.png source should be built.")
|
|
parser.add_argument("--source-dir", type=Path, default=DEFAULT_SOURCE_DIR)
|
|
return parser.parse_args()
|
|
|
|
|
|
def fit_icon(source: Image.Image, size: int) -> Image.Image:
|
|
rgba = source.convert("RGBA")
|
|
bounds = rgba.getchannel("A").getbbox()
|
|
if bounds is None:
|
|
raise ValueError("source image has no visible pixels")
|
|
|
|
cropped = rgba.crop(bounds)
|
|
inner_size = max(1, round(size * 0.88))
|
|
scale = min(inner_size / cropped.width, inner_size / cropped.height)
|
|
resized_size = (
|
|
max(1, round(cropped.width * scale)),
|
|
max(1, round(cropped.height * scale)),
|
|
)
|
|
resized = cropped.resize(resized_size, Image.Resampling.LANCZOS)
|
|
canvas = Image.new("RGBA", (size, size), (0, 0, 0, 0))
|
|
offset = ((size - resized.width) // 2, (size - resized.height) // 2)
|
|
canvas.alpha_composite(resized, offset)
|
|
return canvas
|
|
|
|
|
|
def main() -> None:
|
|
args = parse_args()
|
|
for size in (128, 32):
|
|
(OUTPUT_ROOT / str(size)).mkdir(parents=True, exist_ok=True)
|
|
|
|
for item_id in args.ids:
|
|
source_path = args.source_dir / f"{item_id}-alpha.png"
|
|
if not source_path.exists():
|
|
raise FileNotFoundError(f"missing transparent source: {source_path}")
|
|
|
|
with Image.open(source_path) as source:
|
|
for size in (128, 32):
|
|
output_path = OUTPUT_ROOT / str(size) / f"{item_id}.png"
|
|
fit_icon(source, size).save(output_path, optimize=True)
|
|
print(f"Wrote {output_path.relative_to(ROOT)}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|