Skip to content

Let the document say what colour space a picture is in - #23

Merged
tannevaled merged 1 commit into
mainfrom
calrgb-is-not-direct
Aug 31, 2026
Merged

Let the document say what colour space a picture is in#23
tannevaled merged 1 commit into
mainfrom
calrgb-is-not-direct

Conversation

@tannevaled

@tannevaled tannevaled commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Stacked on #22 (poppler-timeout), which it bases on; the diff to read is the second commit.

The defect

pdfimages lists a /CalRGB picture as rgb and a /CalGray one as grayutils/ImageOutputDev.cc:159-164, read out of the poppler checkout under /Users/Shared/biblio:

case csDeviceGray:
case csCalGray:
    colorspace = "gray";
    break;
case csDeviceRGB:
case csCalRGB:
    colorspace = "rgb";
    break;

Meanwhile the pixels it writes go through colorMap->getRGB (:451), which for a GfxCalRGBColorSpace applies the gamma, the matrix and the chromatic adaptation. So the direct bucket — the one whose agreement figure is about a decoder — admitted pictures poppler had converted, and measured every pixel of them against a colour conversion we did not make. All four pictures still differing by more than four levels after render v0.21.0's chroma fix were /CalRGB.

The rule now

A picture is converted when the listing says so, and also when its own /ColorSpace resolves to CalRGB, CalGray, ICCBased or Lab, whatever the listing says. Only the first two can move anything, since poppler lists ICCBased as icc and Lab as lab and both were converted already; all four are named so the rule is a statement about the document rather than a patch over one judge's table.

The space is read from the picture's own dictionary — through the page's forms as render.Images walks them and to the same depth, and through the resource dictionary when a picture names its space (/CS0) rather than writing it out.

Where it cannot decide, it does not decide quietly. A resource name is unique within one dictionary and not across the several a page reaches, so a page whose two forms each name their own Im1 marks both when either is /CalRGB. That over-counts converted by at most those pictures; the other direction is the one that credits a colour conversion to a codec.

What it moved

Bucket.Calibrated and the record's calibrated say how much of a converted bucket the document accounts for: the pictures whose own /ColorSpace is CIE-based. It is deliberately not the count of what the rule moved, and the code and both READMEs say so — most calibrated pictures are ICCBased or Indexed, which the listing already called converted, so reading it as the change overstates it by two orders of magnitude. What moved is a difference between two runs, and #24 measures it: five pictures fleet-wide, four of them the four /CalRGB DCTDecode pictures this issue names.

Run over the four documents #20 names, as their own population: 4 of their 5 DCTDecode pictures move to converted, calibrated: 4, and the fifth stays direct. The fleet-wide figure comes with the re-measurement at render v0.21.0.

The README now says what the bucket means, including both honesties that remain (index, and an unreadable listing row).

Gate

gofmt, go vet, -race, exact 100% statement coverage and the nine cross-compile targets, all under GOTOOLCHAIN=go1.27.0, GOWORK=off, CGO_ENABLED=0.

Closes #20

@tannevaled
tannevaled changed the base branch from poppler-timeout to main August 31, 2026 13:59
@tannevaled tannevaled closed this Aug 31, 2026
@tannevaled tannevaled reopened this Aug 31, 2026
@tannevaled
tannevaled force-pushed the calrgb-is-not-direct branch from 04e8ff5 to d512e35 Compare August 31, 2026 14:04
@tannevaled
tannevaled force-pushed the calrgb-is-not-direct branch 2 times, most recently from 725f528 to cde0c29 Compare August 31, 2026 17:09
pdfimages lists a /CalRGB picture as "rgb" and a /CalGray one as "gray"
(utils/ImageOutputDev.cc:159-164), while the pixels it writes went through
colorMap->getRGB (:451) — for a GfxCalRGBColorSpace, the gamma, the matrix and
the chromatic adaptation. So the direct bucket admitted pictures poppler HAD
converted, and measured every pixel of them against a colour conversion we did
not make. All four pictures still differing by more than four levels after
render v0.21.0's chroma fix were CalRGB.

The bucket is now decided by both sides: a picture is converted when the
listing says so, and also when its own /ColorSpace resolves to CalRGB, CalGray,
ICCBased or Lab, whatever the listing says. Only the first two can move
anything — poppler lists ICCBased as "icc" and Lab as "lab", both converted
already — and all four are named so the rule is a statement about the document
rather than a patch over one judge's table.

The space is read from the picture's own dictionary, through the page's forms
as render.Images walks them and to the same depth, and through the resource
dictionary when a picture names its space rather than writing it out.

Where it cannot decide it does not decide quietly. A name is unique within one
resource dictionary and not across the several a page reaches, so a page whose
two forms each name their own Im1 marks both when either is CalRGB. That
over-counts converted by at most those pictures; the other direction credits a
colour conversion to a codec, which is what this is about.

Bucket.Calibrated and the record's "calibrated" say how many pictures the
second half of the rule moved, per filter and per bucket, because a rule that
changes a bucket has to be able to say what it changed. On the four documents
issue #20 names, it moves 4 of their 5 DCTDecode pictures and leaves the fifth
where it was.

Closes #20
@tannevaled
tannevaled force-pushed the calrgb-is-not-direct branch from cde0c29 to 6b852da Compare August 31, 2026 17:45
@tannevaled
tannevaled merged commit 3a442bb into main Aug 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The direct bucket admits CalRGB and ICCBased, because pdfimages calls them rgb

1 participant