Skip to content

Pixel-by-pixel comparison with PDFLang

A supplier sends a corrected file. The job is already on the schedule, the press is booked, and somebody has to answer one question before it goes on: is this the document that was approved, with the fix in it — or is it something else?

That question gets answered by eye more often than anyone would like to admit. Two windows side by side, or two proofs on a light table, and a person scrolling. It is the slowest part of the day and the least reliable.

The moment a wrong file goes on press, everything after it is waste. The paper is used. The ink is used. The plates were made for that file. The press time was booked and burnt, and so were the people running it. If it got as far as cutting, folding or binding, that is gone too. If it shipped, there is freight — twice, because it has to come back.

Then the whole job runs again, at full cost, having already spent the budget once.

And the schedule is the part that does not come back. A catalogue that misses the season, a promotion that arrives after the date on it, a magazine that lands a week late: reprinting fixes the artefact, not the moment it was for.

Some of it is not about money at all. A medicine label with the wrong warning text, a legal notice with the wrong figure, a financial document with last quarter’s number — those are not expensive mistakes, they are the kind that end in a recall or a regulator.

Against that, the check costs seconds.

Human attention is very good at spotting a big difference and very poor at spotting a small consistent one. Put two nearly identical pages in front of someone and they will find the paragraph that was rewritten. They will not find the logo that moved two millimetres.

It gets worse with volume. Nobody looks at page 180 the way they looked at page 3. The concentration that catches things is spent early, and the last third of a long document gets a glance rather than a check.

And the result cannot be repeated. Two people comparing the same pair of files will report different things. The same person on a different afternoon will report different things again. When it matters later — when someone asks who approved this and on what basis — there is nothing to show.

pdfl pixelcompare renders both files and compares what they look like, page by page:

Terminal window
pdfl pixelcompare approved.pdf reprint.pdf

It reports one finding per page that changed, with how much of the page is involved and how many separate places it happens in:

page 7: 0.51% of the pixels differ, in 29 area(s)

This is a different question from the one pdfl compare answers. That command looks at the text and the structure. This one looks at the appearance, and the two disagree more often than you would expect.

A logo nudged two millimetres. A hairline rule that vanished. A spot colour swapped for a CMYK build of it. In all three the text is identical, so a text comparison says the files match. They do not match on paper, which is where it counts.

A page that exists in one file and not the other is reported on its own, since there is nothing to compare it against.

A file exported again from the same source often lands a pixel or two off. If that were treated as a difference, every letter on the page would be “different” and the one thing that actually changed would be buried in the noise.

So the comparison looks for a single shift across the whole page, and says so when it finds one:

page 3: 2.10% of the pixels differ, in 44 area(s) (aligned by 2, -1 px)

When the position is what you are checking — an element that must sit in an exact place — --no-align turns that off.

A percentage tells you a page changed. It does not tell you whether the change is acceptable. For that, somebody has to see it:

Terminal window
pdfl pixelcompare approved.pdf reprint.pdf --viewer diff/

That writes a folder with the pages, the differences, and an index.html. No server, no internet, nothing to install. Open the file, or zip the folder and send it to whoever has to sign off the reprint.

It shows three panes side by side, always on the same page: the original, the new file, and both together with the differences painted over them.

Across all three runs a pair of bars, one upright and one flat, in the same place in each. They follow the pointer — there is nothing to grab and nothing to aim at. In the difference pane the bars cut: the new file shows to the right of the upright one and below the flat one, the original everywhere else. In the other two panes the same bars are rulers, marking the same column and the same line of the page, so whatever the wipe uncovers can be found in either original without measuring by eye.

The differences are painted over the page, and the colour says what kind:

Colour Meaning
Red Ink that is gone from the new file
Green Ink that is new in it
Blue Same weight, different colour

The wheel zooms all three panes together, up to 8×, around the point under the pointer — so what you were looking at stays where it was. Holding either mouse button and moving drags the page, again in all three at once, which is how you reach a corner once magnified. Reset view puts zoom, pan and bars back.

And the part that saves the most time: it opens on the pages that differ. On a two-hundred-page document where three pages moved, those three are the reason you opened it, and All puts the rest back. The arrows follow the filter, stepping over what is hidden rather than landing on it.

The exit code carries the verdict, so this can sit in front of the press rather than beside it: 0 when no page changed by more than you allowed, 2 when one did, 10 when a file could not be read at all.

Terminal window
pdfl pixelcompare approved.pdf reprint.pdf --max-diff 0.1 --viewer diff/ || {
echo "the reprint does not match — see diff/index.html"
exit 1
}

--max-diff is the tolerance: how much of a page may change before it counts. --dpi decides how closely to look — higher sees more and takes longer. --threshold and --blur absorb the small noise that rendering produces.

The check runs in seconds, gives the same answer every time, and leaves a report and a viewer behind as the record of what was compared.

The CLI chapter documents every option of pixelcompare, along with compare for the text-and-structure question. The recipes put both inside complete workflows — a print shop checking a press file against the approved proof, a publisher checking a reprint against the edition already on shelves.

DigitalOceanThanks to DigitalOcean for hosting this site.