| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
- from __future__ import annotations
- import json
- import sys
- from pathlib import Path
- from PIL import Image, ImageDraw, ImageFont
- ROOT = Path(sys.argv[1] if len(sys.argv) > 1 else "public/ai-courseware-templates/extracted")
- OUTPUT = Path(sys.argv[2] if len(sys.argv) > 2 else "artifacts/music-template-extraction/extracted-contact-sheets")
- def font(size: int, bold: bool = False):
- path = Path(r"C:\Windows\Fonts\msyhbd.ttc" if bold else r"C:\Windows\Fonts\msyh.ttc")
- try:
- return ImageFont.truetype(str(path), size)
- except OSError:
- return ImageFont.load_default()
- def main() -> None:
- items = json.loads((ROOT / "manifest.json").read_text(encoding="utf-8"))["items"]
- OUTPUT.mkdir(parents=True, exist_ok=True)
- thumb = (150, 84)
- margin = 14
- row_height = 132
- page_size = 6
- width = margin * 11 + thumb[0] * 10
- for page_index, start in enumerate(range(0, len(items), page_size), start=1):
- page_items = items[start:start + page_size]
- canvas = Image.new("RGB", (width, margin + row_height * len(page_items)), "#E9EDF2")
- draw = ImageDraw.Draw(canvas)
- for row, item in enumerate(page_items):
- top = margin + row * row_height
- draw.text((margin, top), f"{item['id']} {item['name']} | {item['scene']}", font=font(20, True), fill="#202631")
- for column, background in enumerate(item["backgrounds"]):
- source = ROOT / item["id"] / Path(background).name
- with Image.open(source) as raw:
- image = raw.convert("RGB").resize(thumb, Image.Resampling.LANCZOS)
- left = margin + column * (thumb[0] + margin)
- image_top = top + 36
- canvas.paste(image, (left, image_top))
- draw.rectangle((left, image_top, left + thumb[0], image_top + thumb[1]), outline="#AEB8C5", width=1)
- canvas.save(OUTPUT / f"templates-{page_index:02d}.jpg", quality=92, optimize=True)
- print(json.dumps({"templates": len(items), "sheets": (len(items) + page_size - 1) // page_size}, ensure_ascii=False))
- if __name__ == "__main__":
- main()
|