Skip to content

Hand back what the codec read, and the mask beside it - #31

Merged
tannevaled merged 1 commit into
mainfrom
images-uncomposited
Aug 29, 2026
Merged

Hand back what the codec read, and the mask beside it#31
tannevaled merged 1 commit into
mainfrom
images-uncomposited

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Images returned what the page draws: the picture with its mask applied. That made it useless for the job it was added for — and worse than useless, because it was wrong in a way that looked like a finding.

Judged against pdfimages over a corpus of scanned pages, 21 of 22 JPEG 2000 pictures came out differing, at a median of 85% of their pixels.

That reading was impossible on its face: the same pages, compared whole against the same renderer, differ by a median of 0.0000. A picture cannot be 85% wrong on a page that is perfect.

Eleven of the twenty-two carry an /SMask. We applied it and pdfimages did not, so the two sides were not being asked the same question.

What changes

Images now hands back what each codec produced, with the mask beside it as its own entry named for the key that named it (I/SMask) — which is what pdfimages does, and the only way the two can be compared. A mask is a picture in its own right, stored in its own filter, and very often the one that is wrong: JBIG2 is almost never a page's content and almost always its mask.

A picture whose mask cannot be read now comes back too. Page still declines to draw that one, because how much of it shows is unknown; the codec read it, and this is about the codec. Both halves are asserted in one test, because it would be easy to move the first and lose the second.

decodeImage keeps its meaning — what the page draws — and is now that composition written down: decodeBase, then the mask.

100% statement coverage, go vet and -race clean, nine cross-compile targets.

Images returned what the PAGE draws: the picture with its mask applied. That
made it useless for the job it was added for, and worse than useless, because
it was wrong in a way that looked like a finding.

Judged against pdfimages over a corpus of scanned pages, 21 of 22 JPEG 2000
pictures came out differing, at a median of 85% of their pixels. That reading
was impossible on its face: the same pages, compared whole against the same
renderer, differ by a median of 0.0000. A picture cannot be 85% wrong on a page
that is perfect.

Eleven of the twenty-two carry an /SMask. We applied it and pdfimages did not,
so the two sides were not being asked the same question.

So Images now hands back what each codec produced, with the mask beside it as
its own entry named for the key that named it — which is what pdfimages does
and the only way the two can be compared. A mask is a picture in its own right,
stored in its own filter, and very often the one that is wrong: JBIG2 is almost
never a page's content and almost always its mask.

A picture whose mask cannot be read now comes back too. Page still declines to
draw that one, because how much of it shows is unknown; the codec read it, and
this is about the codec. Both halves are asserted, in one test, because it
would be easy to move the first and lose the second.

decodeImage keeps its meaning — what the page draws — and is now that
composition written down: decodeBase, then the mask.

100% statement coverage, go vet and -race clean, nine cross-compile targets.
@tannevaled
tannevaled merged commit ef59d83 into main Aug 29, 2026
1 check passed
@tannevaled
tannevaled deleted the images-uncomposited branch August 29, 2026 13:35
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.

1 participant