"""Inspect actual PDF raster pixels at both sidebar edges on every exported page.""" import argparse import json import re from pathlib import Path from PIL import Image, ImageDraw def main(): parser = argparse.ArgumentParser() parser.add_argument("directory", type=Path) args = parser.parse_args() source = json.loads((args.directory / "measurements.json").read_text(encoding="utf-8")) results = [] for fixture in source["fixtures"]: if not fixture["fixture"].endswith(("-technical", "-creative", "-nordic")): continue html = (args.directory / fixture["fixture"] / "render.html").read_text(encoding="utf-8") color = re.search(r"--cv-sidebar-bg:(#[0-9a-fA-F]{6})", html) if not color: continue expected = tuple(int(color[1][index:index + 2], 16) for index in (1, 3, 5)) for number in range(1, fixture["previewPages"] + 1): with Image.open(args.directory / fixture["fixture"] / f"pdf-{number}.png") as image: image = image.convert("RGB") # 2px and 8px lie inside the bleed and outside the 8mm text padding. columns = [image.width - 3, image.width - 9] if fixture["fixture"].endswith("-nordic") else [2, 8] samples = [] for x in columns: mismatched = [y for y in range(image.height) if max(abs(a - b) for a, b in zip(image.getpixel((x, y)), expected)) > 2] samples.append({"x": x, "expectedRgb": expected, "height": image.height, "mismatchedRows": len(mismatched), "firstMismatchRows": mismatched[:8], "topPixel": image.getpixel((x, 0)), "bottomPixel": image.getpixel((x, image.height - 1))}) results.append({"fixture": fixture["fixture"], "page": number, "pass": all(sample["mismatchedRows"] == 0 for sample in samples), "samples": samples}) report = {"rasterizer": "pypdfium2 via unchanged verify-cv-fidelity.py, actual exported PDF bytes", "colorTolerancePerChannel": 2, "passedPages": sum(item["pass"] for item in results), "pages": len(results), "results": results} (args.directory / "sidebar-pixels.json").write_text(json.dumps(report, indent=2), encoding="utf-8") print(f"Full-height sidebar raster coverage: {report['passedPages']}/{report['pages']} pages") # Contact sheets use independent Poppler first/last rasterizations. for sample in ("short-en", "medium-nb", "long-en", "dense-nb"): fixtures = [item for item in source["fixtures"] if item["fixture"].startswith(sample + "-")] for edge in ("first", "last"): sheet = Image.new("RGB", (900, 1365), "#e5e7eb") draw = ImageDraw.Draw(sheet) for index, fixture in enumerate(fixtures): page = 1 if edge == "first" else fixture["previewPages"] filename = args.directory / fixture["fixture"] / f"poppler-{page}.png" if not filename.exists(): raise FileNotFoundError(filename) with Image.open(filename) as image: image = image.convert("RGB") image.thumbnail((286, 414)) x, y = (index % 3) * 300 + 7, (index // 3) * 455 + 32 sheet.paste(image, (x, y)) draw.text((x, y - 25), f"{fixture['fixture']} p{page}/{fixture['previewPages']}", fill="#111827") sheet.save(args.directory / f"contact-{sample}-{edge}.png") raise SystemExit(0 if report["passedPages"] == report["pages"] and report["pages"] > 0 else 1) if __name__ == "__main__": main()