build_extracted_template_contact_sheets.py 2.1 KB

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