Pair a picture with the judge's by its object number - #28
Merged
Merged
Conversation
Refs #13. The matcher paired our picture with the first unclaimed picture of THEIRS of the same size. Its own comment said that was "right as often as it is wrong and is reported either way" -- and it was not reported either way. Page 1 of cerfa_10074.pdf draws 211 distinct 2x2 pictures whose stream bytes are all "00 00": uniform swatches, all ink or all paper, stretched under an /SMask that carries the glyph shapes. Two orders over 211 same-size swatches pair a black one with a white one, difference reads 1.0, and Judge writes Inverted. The object number is the one identity BOTH sides publish -- theirs in the object column of pdfimages -list, ours by resolving the resource name render.Images hands back through the same resource graph calibratedNames walks. Paired on that, over fr-cerfa page 1: (samples), 3404 pictures size and order object identity direct exact 186 of 418 418 of 418 differing 232 0 converted exact 1093 of 2949 2804 of 2949 INVERTED 68 0 differing 1788 145 DCTDecode, worst of the converted bucket peak 255 43 mse 31435.6 118.4 The 68 inversions were the pairing. The 15 that survive elsewhere are the stencil-polarity convention, which is what #13 said should survive and does. A converted bucket whose worst error was 255 levels and 31 435 MSE -- a maximal disagreement -- was a picture compared against one it had nothing to do with. Three things the identity does not settle by itself, all conservative: A picture and its soft mask are listed under the SAME object number, so the row's type has to agree as well: ours is a mask or it is not. A name that reaches two different objects is dropped rather than guessed at. A name is unique within one resource dictionary and not across the several a page reaches through its forms, so a page whose two forms each name their own Im1 has one ambiguous name and everything else still paired by identity. A wrong identity is worse than none. A poppler that lists no object column, an inline picture with no object number, and a name nobody listed all fall back to the size rule, which is where they were before. Result.PairedBy now records which was used, so a run leaning on size is visible rather than assumed. 100% statement coverage, race clean, nine cross-build targets, Go 1.27.1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 7, 2026
tannevaled
added a commit
that referenced
this pull request
Sep 7, 2026
The records described a library measured through an instrument that has since been replaced. #28 stopped pairing a picture with the first unclaimed picture of poppler's OF THE SAME SIZE and began pairing by object number, so every `inverted` and `differing` figure taken before it was partly an artefact of how the two sides were lined up. Everything else was held, and checked BEFORE the run rather than asserted after it: the same judge (pdfimages 26.04.0), the same five module versions, one page per document, the same two-minute bound. The measure is the only thing that moved, which is what this file demands of any figure it prints. Over all 23 populations and the same 7515 compared pictures: 2026-08-31 2026-09-07 pictures compared 7515 7515 exact 4611 6598 reported inverted 488 422 reported differing 2416 495 agreement 65.6% 93.0% Six populations moved; seventeen are identical to the byte. The picture count is unchanged, so none of it comes from measuring less. It is not uniformly "fewer inversions". ia-uscourts GAINED two, 37 to 39, while its differing count fell by the same two: the right pairing found two genuine complements the wrong one had hidden inside a disagreement. A change that only ever removed inversions would be a change that only ever flattered. Section 8 said "Inversions are unchanged, and still conventions". This run disproves it, so it is rewritten rather than left standing -- with what it got right kept, since the complements on the mask filters ARE the convention and did not move. Section 9 is new: with the pairing fixed, every lossless path is at or near the top -- JPXDecode 100.0%, (samples) 97.4%, the mask filters 96.3% and 100.0% -- and DCTDecode sits at 43.7%, having moved 0.5 points because the pairing was never its problem. That is the shape of the remaining work, and the old numbers hid it: at 69.7% against 43.2% the two looked like the same kind of problem at different depths, and only one of them is a codec difference worth a library change. Sections 1-7 are about the earlier comparison and are kept as that, with a note at the head of the analysis saying so. Section 7's own table is refreshed and its claim re-checked: every agreeing picture of every lossless filter is still bit-equal. Every table here was regenerated by a script proved against the PREVIOUS README first -- all 31 population rows, all 8 filter rows and all 39 bucket rows reproduced verbatim from the old records before it was pointed at the new ones. A first draft of it silently dropped the two populations that draw no pictures; that is why the proof is run in that direction. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
tannevaled
added a commit
that referenced
this pull request
Sep 7, 2026
) The fallback exists for when the object number cannot answer: an older poppler with no object column, or a picture whose object this side could not find. It was also running when BOTH sides published a number and the two simply differed -- which does not mean "look harder", it means the judge did not extract this picture. Taking a row anyway costs twice. 2044_2044_4764.pdf holds ten 118x118 Data Matrix barcodes in one shared resource dictionary; a barcode the page never draws was paired with the row belonging to the one it does, reported 255 apart on every term, and the barcode that WAS drawn came back unpaired and unmeasured. Over the corpus, 30 of the 41 structural JPEG disagreements were pairs like that. The stand-in judge wrote object 7 on every listing row, and 7 is not an object any of these fixtures holds. So every end-to-end test here was pairing by SIZE, and the by-object path added in #28 was reached by the unit tests alone -- the fixture agreed with nothing, which is why it never contradicted anything. It now reports the object numbers the file actually holds, read by scanning its bytes rather than by asking this package, and the end-to-end tests pair by object as the corpus does. standInWithoutObjects keeps the older-poppler case honest and explicit. Making the stand-in faithful uncovered a silent refusal: a pair whose two sides come out different sizes has no pixel to set against a pixel, and came back with Share -1 and no note -- which reads exactly like an agreement of zero. It now says both sizes. 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.
Refs #13.
images.matchpaired our picture with the first unclaimed picture of theirs of the same size. Its own comment said that was "right as often as it is wrong and is reported either way" — and it was not reported either way.Page 1 of
cerfa_10074.pdfdraws 211 distinct 2×2 pictures whose stream bytes are all00 00: uniform swatches, all ink or all paper, stretched under an/SMaskthat carries the glyph shapes. Two orders over 211 same-size swatches pair a black one with a white one,differencereads 1.0, andJudgewritesInverted.The object number is the one identity both sides publish — theirs in the
objectcolumn ofpdfimages -list, ours by resolving the resource namerender.Imageshands back, through the same resource graphcalibratedNamesalready walks.Measured, paired: same corpus, same command, one variable
fr-cerfapage 1,(samples), 3404 pictures:And the worst of
DCTDecode's converted bucket, which was a maximal disagreement:A picture was being compared against one it had nothing to do with. The 68 inversions were the pairing. The 15 that survive elsewhere are the stencil-polarity convention — which #13 says should survive, and does.
Three things identity does not settle by itself
objectcolumn, an inline picture with no object number, and a name nobody listed all fall back to the size rule, which is where they were before.Result.PairedBynow records which was used, so a run leaning on size is visible rather than assumed.This does not close #13: its parts 2 and 3 — what
pdfimagesdoes with an/Indexedpalette that is not exactly black, and theus-opmstencil polarity — are separate findings about the judge, not about the matcher.100% statement coverage, race clean, nine cross-build targets, Go 1.27.1.
🤖 Generated with Claude Code