Skip to content

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

Description

@tannevaled

Found while diagnosing go-pdfkit/render#40. Recorded, not fixed.

images/images.go splits a comparison into direct and converted on the colour space pdfimages -list reports:

var direct = map[string]bool{"gray": true, "rgb": true, "-": true}

The converted bucket exists so that "poppler had to convert the picture's colour space to reach RGB" is not charged to a codec. It does not catch what it is meant to catch, because pdfimages calls a /CalRGB picture rgb:

// poppler/utils/ImageOutputDev.cc:162-164
case csDeviceRGB:
case csCalRGB:
    colorspace = "rgb";

and the write path lumps 3-component csICCBased in with them as well (utils/ImageOutputDev.cc:648 and :676). Meanwhile the pixels poppler writes go through colorMap->getRGB (utils/ImageOutputDev.cc:451), which for GfxCalRGBColorSpace applies the gamma, the matrix and the chromatic adaptation. So a CalRGB picture lands in direct and every pixel of it is measured against a colour conversion we did not make.

What it costs, measured

Over 559 DCTDecode pictures that pdfimages reports as gray or rgb across both corpora, decoded with libjpeg's chroma reconstruction so that render#40's defect is out of the way, four still differ from poppler by more than 4 levels — and all four are /CalRGB:

picture peak space
gh-openpdf/…PDF_2.0_image_with_BPC.pdf 110 /CalRGB, white point [0.9643 1 0.8251] — D50
fr-cerfa/cerfa_11616.pdf, cerfa_11612.pdf 10 /CalRGB, gamma 2.22221
fr-cerfa/cerfa_12625.pdf 11 /CalRGB, gamma 2.22221

Nothing else in those 559 exceeds 4. On cerfa_11616 poppler differs from djpeg's own output of the same extracted stream by peak 9 over 12.5% of the picture, which is the conversion, not the codec — and it is another instance of the judge not being the oracle.

What it would take

pdfimages -list cannot tell CalRGB from DeviceRGB, so the colour space has to be read from the picture's own dictionary rather than from the judge's listing: an /XObject whose /ColorSpace resolves to [/CalRGB …], [/CalGray …] or [/ICCBased …] belongs in converted, whatever poppler's listing says. That is a real change to how a picture is classified and wants its own measurement of how many pictures move, so it is filed rather than done.

Four pictures of 559 is not much. It is filed anyway because the number is small only until a population of ICC-tagged scans arrives, and because a bucket that silently admits what it was built to exclude misleads in the direction of comfort.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions