Files
2026-09-21 13:41:40 +09:00

51 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ICC rendering-intent regression corpus
`rendering-intents.pdf` contains 8 pages and 200 interior-color probes. It is self-authored PDF 1.7 test material, with no borrowed press characterization or renderer-generated golden. Its SHA-256 is `ce59287f6cb2c256c87fcea00a183fa655a165e5028056f28c8c78ddea6645b8`. Exact probe coordinates, intended graphics states, content operators and source hashes are in [manifest.json](manifest.json).
Two ICC v2 CMYK→Lab input profiles exercise the same PDF operations:
- `original-cmyk-lab.icc` is byte-identical to the existing `../cmyk-lut/synthetic-cmyk-lab.icc` (SHA-256 `1708392182ecb3819bb0e4bd1139677be24c9884fff84ad3bb91af5dd42b78f7`). Its A2B0 table alone cannot distinguish Relative, Saturation and Absolute.
- `distinct-cmyk-lab.icc` extends that self-authored binary layout with separate A2B0/A2B1/A2B2 linear CLUTs and media white point `(0.82, 0.86, 0.72)` (SHA-256 `b9a40bfc18e8280eefe0fedc4e607467e1cc27adeee3beb77f4a2b83fc7e9315`). The A2B1/A2B2 black endpoint is Lab `(0,0,0)` to isolate intent selection from a CMM's optional black-point compensation. The original profile is unchanged.
For CMYK bytes `(51,128,204,77)`, direct LittleCMS 2.19 and Pillow/LittleCMS produce these RGB values:
| Intent | Original profile | Distinct profile |
|---|---|---|
| Perceptual | 187,165,145 | 187,165,145 |
| RelativeColorimetric | 193,171,151 | 166,132,101 |
| Saturation | 193,171,151 | 127,143,114 |
| AbsoluteColorimetric | 193,171,151 | 153,124,95 |
The smallest pairwise maximum-channel difference in the distinct profile is 13, greater than twice the fixed 4-level raster tolerance. The runner independently verifies all 64 CLUT vertices from coefficient equations, then computes reference colors directly from the ICC bytes and expected intent using public LittleCMS APIs with floating-point CMYK input. Pillow's 8-bit path cross-checks the eight sample colors within one level. A separate check confirms black-point compensation does not change the distinct-profile sample for any intent. This oracle does not read rendered pixels, but may share LittleCMS algorithms with PDFium/Poppler; it is not an independent CMM implementation.
The matrix covers all four standard intents, with the declared default and override expectations preserved:
- `ri` and ExtGState `/RI`; nested `q/Q` changes and restoration.
- Shared Form XObject inheritance through `ri` and `gs`; Form content `ri`/`gs` override; caller state restored after the Form returns.
- One Image XObject without `/Intent`, reused in forward/reverse intent order and with `gs` order Perceptual→Relative→Perceptual→Absolute. Image dictionary `/Intent` overrides the caller and does not change the following vector's state.
- Indexed ICC vector and image; stroking color; standard-font text; axial shading.
- Shading patterns inheriting the caller, and pattern ExtGState `/RI` override.
- Colored Type3 `d0` glyphs with rectangles or images, reusing the same font and charcode 65 under four caller intents, plus glyph-content `ri` override.
Type3 glyph probe points lie inside a large filled rectangle. Standard-font text samples the interior of the Helvetica-Bold `H` stem. Shading expectations account for the actual sampled raster pixel center. The corpus does not cover unknown intent names, malformed intent types, soft-mask luminosity/compositing, tiling patterns, real printing profiles, arbitrary ICC profiles, physical displays, Windows or human-approved golden images.
## Generate and validate
Use Python with pypdf and Pillow; validation also needs a shared LittleCMS2 library. Full comparisons require qpdf, pdftoppm and the project's `pdf-worker-evidence`/`docview-pdf-worker` binaries. A fresh output directory is mandatory.
```sh
python3 tests/fixtures/pdf/generate_rendering_intents.py --output /path/to/new-corpus
python3 tests/cmyk_lut/intents.py --self-check --output /path/to/new-self-check
python3 tests/cmyk_lut/intents.py --build-dir build \
--pdfium-library /path/to/selected/libpdfium.so \
--scales 0.5 1 2 --output /path/to/new-comparison
```
`--corpus` selects a newly generated corpus if needed. `--pdfium-library` prepends its directory to the child's library path, verifies the actual `ldd` resolution before rendering, and records its hash; an RPATH selection mismatch fails. The normal worker sandbox and font broker remain active. The script does not replace any installed library.
`--self-check` exits successfully after validating the fixture/CMM, but deliberately records `success:false` and `renderingAcceptance:false`: it is not a rendering pass. A full report records PDFium and Poppler results separately; overall success currently requires both renderers, all probes and unchanged inputs/binaries. A failed comparison retains every probe and its exact CMM error, command logs, hashes and comparison images. The tolerance is not relaxed for another renderer's discrepancy.
During initial 1× validation, the fixed unmodified PDFium baseline failed 150/200 probes, consistently exposing its Perceptual-only conversion. Poppler 26.05.0 matched 194/200; the six failures were confined to shading-pattern ExtGState `/RI` override, where its color matched the caller intent. These are diagnostic observations, not acceptance of either mismatch. Final patched-renderer results belong in separate evidence directories. Independent regeneration reproduced all four generated files byte-for-byte.
References: [ISO 32000-1, clauses 8.4, 8.6.5.8, 8.7.4, 8.9.5, 8.10 and 9.6.5](https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf), [ICC v2 specification](https://archive.color.org/files/icc32.pdf), [LittleCMS](https://www.littlecms.com/).