import json import sys from pathlib import Path from PIL import Image, ImageOps from pptx import Presentation from pptx.util import Inches def main() -> None: if len(sys.argv) != 3: raise SystemExit("Usage: python html_to_ppt_make.py ") image_dir = Path(sys.argv[1]) output_pptx = Path(sys.argv[2]) output_pptx.parent.mkdir(parents=True, exist_ok=True) labels_path = image_dir / "slides.json" labels = {} if labels_path.exists(): labels = {item["index"]: item["label"] for item in json.loads(labels_path.read_text(encoding="utf-8"))} image_paths = sorted(image_dir.glob("slide_*.png")) if not image_paths: raise SystemExit(f"No slide PNGs found in {image_dir}") prs = Presentation() prs.slide_width = Inches(13.333333) prs.slide_height = Inches(7.5) blank_layout = prs.slide_layouts[6] for image_path in image_paths: slide_num = int(image_path.stem.split("_")[-1]) slide = prs.slides.add_slide(blank_layout) picture = slide.shapes.add_picture( str(image_path), 0, 0, width=prs.slide_width, height=prs.slide_height, ) picture.name = labels.get(slide_num, image_path.stem) prs.save(output_pptx) montage_path = output_pptx.with_suffix(".preview.png") thumbs = [] for image_path in image_paths: img = Image.open(image_path).convert("RGB") img.thumbnail((384, 216), Image.Resampling.LANCZOS) thumbs.append(ImageOps.expand(img, border=2, fill=(30, 30, 30))) cols = 5 rows = (len(thumbs) + cols - 1) // cols montage = Image.new("RGB", (cols * 388, rows * 220), (12, 15, 24)) for idx, thumb in enumerate(thumbs): x = (idx % cols) * 388 y = (idx // cols) * 220 montage.paste(thumb, (x, y)) montage.save(montage_path) print(f"pptx={output_pptx}") print(f"preview={montage_path}") print(f"slides={len(image_paths)}") if __name__ == "__main__": main()