A stencil needs decoded bytes, not compressed ones - #20
Merged
Conversation
decodeImage asks whether an image is a mask before it asks whether the filter chain finished, so a mask whose filter stopped at an image format nothing here decodes was handed to the stencil path still compressed — and drawn. A stencil is one bit a pixel; compressed bytes painted through it are noise in the shape of nothing at all. This is not a rare shape. 273 of the image masks in the 1 633 real forms carry an encoded filter: 236 CCITT and 9 JBIG2. Fifty-one first pages of real forms were showing that noise, and it took decoding faxes in the reader (go-pdfkit/reader#15) to make it visible: those pages came out with *less* ink afterwards, because most of a form is white and the noise was not. The remaining nine are JBIG2, which nothing here decodes. Until something does, the honest answer is the one the rest of decodeImage already gives: "the image is not drawn rather than drawn wrong." The test draws a mask of eight zero bytes — as samples, a solid black stencil, so anything drawn at all is visible — once with /Filter /JBIG2Decode and once with no filter, and requires the first to draw nothing and the second to draw. Against the parent commit the first fails with "drawn = true, want false". 100% statement coverage, go vet clean, nine cross-compile targets. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merged
tannevaled
added a commit
that referenced
this pull request
Aug 27, 2026
reader v0.5.0 decodes /CCITTFaxDecode. 67 of the 1 633 real forms in the corpus carry a fax and 6 of their pages have nothing else on them, so those pages drew blank; requiring an older reader here would leave them blank for anyone who asked only for this package, since minimum version selection gives them the version this go.mod names. fax_test.go guards it with a fax rather than a version string: one Group 4 row, three white pixels then five black, coded in horizontal mode and built in the test so nobody else's scan enters the repository. Against reader v0.4.2 it fails with "the black part of the fax is not black: (6,4) = 255,255,255,255". Measured through this package over the first page of all 1 633 real forms, 69 pages change: one from blank to drawn (fr-cerfa/cerfa_11818, 0 inked pixels to 28 989), fourteen with more ink, and fifty-one with less — those were showing their own compressed bytes as a stencil, which #20 stopped and this finishes. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
decodeImage asks whether an image is a mask before it asks whether the filter
chain finished, so a mask whose filter stopped at an image format nothing here
decodes was handed to the stencil path still compressed — and drawn. A stencil
is one bit a pixel; compressed bytes painted through it are noise in the shape
of nothing at all.
This is not a rare shape. 273 of the image masks in the 1 633 real forms carry
an encoded filter: 236 CCITT and 9 JBIG2. Fifty-one first pages of real forms
were showing that noise, and it took decoding faxes in the reader
(go-pdfkit/reader#15) to make it visible: those pages came out with less ink
afterwards, because most of a form is white and the noise was not.
The remaining nine are JBIG2, which nothing here decodes. Until something does,
the honest answer is the one the rest of decodeImage already gives: "the image
is not drawn rather than drawn wrong."
The test draws a mask of eight zero bytes — as samples, a solid black stencil,
so anything drawn at all is visible — once with /Filter /JBIG2Decode and once
with no filter, and requires the first to draw nothing and the second to draw.
Against the parent commit the first fails with "drawn = true, want false".
100% statement coverage, go vet clean, nine cross-compile targets.