#!/usr/bin/env python3 """Build a non-production grid placement guide with centered safe envelopes.""" from __future__ import annotations import argparse from pathlib import Path from PIL import Image, ImageDraw def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--rows", type=int, required=True) parser.add_argument("--cols", type=int, required=True) parser.add_argument("--width", type=int, required=True) parser.add_argument("--height", type=int, required=True) parser.add_argument("--output", type=Path, required=True) return parser.parse_args() def main() -> None: args = parse_args() if min(args.rows, args.cols, args.width, args.height) < 1: raise SystemExit("all dimensions must be positive") image = Image.new("RGB", (args.width, args.height), (0, 255, 0)) draw = ImageDraw.Draw(image) for row in range(args.rows): for col in range(args.cols): left = round(col * args.width / args.cols) right = round((col + 1) * args.width / args.cols) top = round(row * args.height / args.rows) bottom = round((row + 1) * args.height / args.rows) cell_w, cell_h = right - left, bottom - top margin_x, margin_y = round(cell_w * 0.23), round(cell_h * 0.23) box = (left + margin_x, top + margin_y, right - margin_x, bottom - margin_y) draw.rectangle(box, outline=(42, 48, 60), width=6) cx, cy = (left + right) // 2, (top + bottom) // 2 draw.line((cx - 18, cy, cx + 18, cy), fill=(240, 240, 232), width=4) draw.line((cx, cy - 18, cx, cy + 18), fill=(240, 240, 232), width=4) args.output.parent.mkdir(parents=True, exist_ok=True) image.save(args.output, optimize=True) print(f"GRID_LAYOUT_GUIDE_OK cells={args.rows * args.cols} output={args.output}") if __name__ == "__main__": main()