← Files Comic SolARCHIVED FILE

skills/comic-sol/scripts/pdf_quality.py

7.73 KB · Sep 30, 2026 · 23:14 UTC

↓ Download file

#!/usr/bin/env python3
"""Full-content raster verification for Comic Sol PDF exports."""

from __future__ import annotations

import io
import re
import warnings
from dataclasses import asdict, dataclass
from typing import Sequence

from PIL import Image, ImageChops

# One global raster decode budget keeps every Image.open path fail-closed against
# crafted decompression bombs, while project-specific decoded-size checks remain
# in place for lettering and normalization. Pages are 1600x2400; sixteen page
# areas is the generous ceiling for oversampled source art.
Image.MAX_IMAGE_PIXELS = 1600 * 2400 * 16

PDF_TOLERANCE_VERSION = "1"
PDF_EXPORTER_VERSION = "comic-sol-pillow-raster-v1"

# Calibrated against Pillow 12.2 JPEG-in-PDF round trips containing flat color,
# sharp borders, one-pixel lines, and small lettering. The accepted ceilings add
# margin above the pinned fixture while remaining below every corruption fixture.
MAX_MEAN_ABSOLUTE_CHANNEL_ERROR = 3.1
HIGH_ERROR_CHANNEL_THRESHOLD = 24
MAX_HIGH_ERROR_PIXEL_RATIO = 0.021
GRID_COLUMNS = 8
GRID_ROWS = 8
MAX_GRID_REGION_ERROR = 16.0

_PDF_STREAM_PATTERN = re.compile(rb"stream\r?\n(.*?)\r?\nendstream", re.DOTALL)


class PdfQualityError(ValueError):
    """Raised when a PDF cannot prove full-page raster fidelity."""


@dataclass(frozen=True)
class PdfPageMetrics:
    page_number: int
    dimensions: tuple[int, int]
    mode: str
    compared_pixels: int
    mean_absolute_channel_error: float
    high_error_pixel_ratio: float
    maximum_grid_region_error: float


def _rounded(numerator: int, denominator: int) -> float:
    return round(numerator / denominator, 6) if denominator else 0.0


def compare_full_page(
    source: Image.Image,
    decoded: Image.Image,
    *,
    page_number: int = 1,
) -> PdfPageMetrics:
    """Compare every source/decoded pixel using deterministic integer sums."""
    if source.size != decoded.size:
        raise PdfQualityError(
            f"decoded PDF page {page_number} dimensions do not match source"
        )
    source_rgb = source.convert("RGB")
    decoded_rgb = decoded.convert("RGB")
    try:
        width, height = source_rgb.size
        difference = ImageChops.difference(source_rgb, decoded_rgb)
        try:
            histogram = difference.histogram()
            total_error = sum(
                value * count
                for channel in range(3)
                for value, count in enumerate(
                    histogram[channel * 256:(channel + 1) * 256]
                )
            )
            high_error_lut = [
                255 if value > HIGH_ERROR_CHANNEL_THRESHOLD else 0
                for value in range(256)
            ]
            masks = [
                channel.point(high_error_lut)
                for channel in difference.split()
            ]
            try:
                high_mask = ImageChops.lighter(
                    ImageChops.lighter(masks[0], masks[1]), masks[2]
                )
                high_error_pixels = width * height - high_mask.histogram()[0]
                high_mask.close()
            finally:
                for mask in masks:
                    mask.close()

            region_means: list[float] = []
            for row in range(GRID_ROWS):
                top = row * height // GRID_ROWS
                bottom = (row + 1) * height // GRID_ROWS
                for column in range(GRID_COLUMNS):
                    left = column * width // GRID_COLUMNS
                    right = (column + 1) * width // GRID_COLUMNS
                    region = difference.crop((left, top, right, bottom))
                    try:
                        region_histogram = region.histogram()
                        region_error = sum(
                            value * count
                            for channel in range(3)
                            for value, count in enumerate(
                                region_histogram[channel * 256:(channel + 1) * 256]
                            )
                        )
                        region_means.append(
                            _rounded(region_error, (right - left) * (bottom - top) * 3)
                        )
                    finally:
                        region.close()
        finally:
            difference.close()
        return PdfPageMetrics(
            page_number=page_number,
            dimensions=(width, height),
            mode="RGB",
            compared_pixels=width * height,
            mean_absolute_channel_error=_rounded(total_error, width * height * 3),
            high_error_pixel_ratio=_rounded(high_error_pixels, width * height),
            maximum_grid_region_error=max(region_means, default=0.0),
        )
    finally:
        source_rgb.close()
        decoded_rgb.close()


def _decode_pdf_frames(payload: bytes) -> list[Image.Image]:
    if not payload.startswith(b"%PDF-") or not payload.rstrip().endswith(b"%%EOF"):
        raise PdfQualityError("PDF payload is corrupt or truncated")
    frames: list[Image.Image] = []
    for match in _PDF_STREAM_PATTERN.finditer(payload):
        stream = match.group(1)
        if not stream.startswith(b"\xff\xd8"):
            continue
        try:
            with warnings.catch_warnings():
                warnings.simplefilter("error", Image.DecompressionBombWarning)
                with Image.open(io.BytesIO(stream)) as image:
                    image.load()
                    frame = image.convert("RGB")
                    frame.load()
                    frames.append(frame)
        except (OSError, SyntaxError, Image.DecompressionBombError, Image.DecompressionBombWarning) as error:
            for frame in frames:
                frame.close()
            raise PdfQualityError("PDF raster frame could not be decoded") from error
    if not frames:
        raise PdfQualityError("PDF payload contains no decodable raster pages")
    return frames


def _metrics_pass(metrics: PdfPageMetrics) -> bool:
    return (
        metrics.mean_absolute_channel_error <= MAX_MEAN_ABSOLUTE_CHANNEL_ERROR
        and metrics.high_error_pixel_ratio <= MAX_HIGH_ERROR_PIXEL_RATIO
        and metrics.maximum_grid_region_error <= MAX_GRID_REGION_ERROR
    )


def verify_pdf_payload(
    payload: bytes,
    source_pages: Sequence[Image.Image],
) -> dict[str, object]:
    """Decode and compare every PDF page against ordered source rasters."""
    frames = _decode_pdf_frames(payload)
    try:
        if len(frames) != len(source_pages):
            raise PdfQualityError("written PDF page count does not match source pages")
        metrics: list[PdfPageMetrics] = []
        for page_number, (source, decoded) in enumerate(
            zip(source_pages, frames), 1
        ):
            page_metrics = compare_full_page(
                source, decoded, page_number=page_number
            )
            if not _metrics_pass(page_metrics):
                raise PdfQualityError(
                    f"written PDF content mismatch at page {page_number}"
                )
            metrics.append(page_metrics)
        return {
            "exporter_version": PDF_EXPORTER_VERSION,
            "page_count": len(metrics),
            "pages": [
                {
                    **asdict(page),
                    "dimensions": list(page.dimensions),
                }
                for page in metrics
            ],
            "tolerance": {
                "grid": [GRID_COLUMNS, GRID_ROWS],
                "high_error_channel_threshold": HIGH_ERROR_CHANNEL_THRESHOLD,
                "max_grid_region_error": MAX_GRID_REGION_ERROR,
                "max_high_error_pixel_ratio": MAX_HIGH_ERROR_PIXEL_RATIO,
                "max_mean_absolute_channel_error": MAX_MEAN_ABSOLUTE_CHANNEL_ERROR,
                "version": PDF_TOLERANCE_VERSION,
            },
        }
    finally:
        for frame in frames:
            frame.close()

SHA-256: 16eebace472e557969e0f573e7fe22e3a001e9e4f2aa94c7d5a13c263a0096f8