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.
Found while diagnosing go-pdfkit/render#40. Recorded, not fixed.
images/images.gosplits a comparison intodirectandconvertedon the colour spacepdfimages -listreports:The
convertedbucket 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, becausepdfimagescalls a/CalRGBpicturergb:and the write path lumps 3-component
csICCBasedin with them as well (utils/ImageOutputDev.cc:648and:676). Meanwhile the pixels poppler writes go throughcolorMap->getRGB(utils/ImageOutputDev.cc:451), which forGfxCalRGBColorSpaceapplies the gamma, the matrix and the chromatic adaptation. So a CalRGB picture lands indirectand every pixel of it is measured against a colour conversion we did not make.What it costs, measured
Over 559
DCTDecodepictures thatpdfimagesreports asgrayorrgbacross 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:gh-openpdf/…PDF_2.0_image_with_BPC.pdf/CalRGB, white point[0.9643 1 0.8251]— D50fr-cerfa/cerfa_11616.pdf,cerfa_11612.pdf/CalRGB, gamma 2.22221fr-cerfa/cerfa_12625.pdf/CalRGB, gamma 2.22221Nothing else in those 559 exceeds 4. On
cerfa_11616poppler differs fromdjpeg'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 -listcannot 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/XObjectwhose/ColorSpaceresolves to[/CalRGB …],[/CalGray …]or[/ICCBased …]belongs inconverted, 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.