Read CalGray and CalRGB, and let a JPEG reach its colour space - #50
Merged
Conversation
Two defects, and the second is what made the first unreachable. CalGray and CalRGB were read as DeviceGray and DeviceRGB. They are not: each says what CIE XYZ its numbers stand for under a white point of its own, so reaching sRGB is a gamma, a matrix and a chromatic adaptation. With the gamma the format defaults to, a CalGray component is linear luminance and a mid grey encodes to 188 rather than 128. calibrated.go reads the two dictionaries and gfx/color v0.22.0 does the arithmetic. jpegThroughSpace then asked the colour space only for a ONE-component picture in one of four named families, so a three-component JPEG in a calibrated space was drawn from the decoder's own colours and the space was never consulted. The rule is now what it should always have been: a space that is not one of the four device singletons has something to say about the samples, whatever their count. Measured on openpdf's PDF 2.0 test file, whose two pictures are the SAME 1466-byte JPEG stream drawn once through a CalRGB and once through DeviceRGB, and whose own page text says they must differ: peak 110 -> 20 share 0.5764 -> 0.0098 mse 909.34 -> 0.30 The 20 that remains is not colour. Our conversion applied to poppler's own decoded samples disagrees with poppler by ONE level; but a sample error of +/-3, which is exactly what the direct bucket measures for this same stream, moves the answer by up to 35 levels once a gamma of 2.2 and an Adobe RGB matrix have amplified it. A calibrated space magnifies a decoder disagreement, which is worth knowing before reading any per-channel bound. Lab is deliberately left as it was. poppler's GfxLabColorSpace does not multiply by the white point where ISO 32000-2 8.6.5.4 says to, so a correct Lab and the judge would disagree for a reason that is not ours; that wants an experiment of its own. 12 of 2268 form documents mention /Lab, none of the 1013 scans.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects, and the second is what made the first unreachable.
The spaces were read as their device namesakes
CalGrayandCalRGBwere mapped straight ontoDeviceGrayandDeviceRGB. They are not those spaces: each says what CIE XYZ its numbers stand for, under a white point of its own choosing, so reaching sRGB is a gamma, a matrix and a chromatic adaptation.With the gamma the format defaults to, a
CalGraycomponent is linear luminance — a mid grey encodes to 188, not the 128 a device grey gives.calibrated.goreads the two dictionaries and carries the format defaults;gfx/colorv0.22.0 does the arithmetic (go-gfx/gfx#39, measured against poppler at 1 level in 256).And a JPEG could not reach a colour space anyway
jpegThroughSpaceasked the colour space only for a one-component picture in one of four named families:So a three-component JPEG in a calibrated space was drawn from the decoder’s own colours and the space was never consulted — the new library would have had no caller. The rule is now what it should have been: a space that is not one of the four device singletons has something to say about the samples, whatever their count. The device spaces are package-level singletons, so identity is the whole test.
What it is worth
openpdf’s PDF 2.0 test file draws the same 1466-byte JPEG stream twice, once through a
CalRGB(Adobe RGB matrix, D50, gamma 2.2) and once throughDeviceRGB, and its own page text says the two should differ. Againstpdfimages:The 20 that remains is not colour
Our conversion applied to poppler’s own decoded samples disagrees with poppler by one level. But a sample error of ±3 — exactly what the
directbucket measures for this same stream — moves the answer by up to 35 levels once a gamma of 2.2 and an Adobe RGB matrix have amplified it.A calibrated space magnifies a decoder disagreement. That is worth knowing before reading any per-channel bound: the conformance gate is derived for a picture read directly.
Lab is deliberately left alone
Labis unchanged in this PR. For scale: 12 of 2268 form documents mention/Lab, and none of the 1013 scans.Coverage stays at 100%.
🤖 Generated with Claude Code