How to verify the pixels did not change.

Pixel identity is the strongest claim this tool makes, and you should not take the test suite's word for it. Here is how to check it yourself.

~2 minutes macOS · Linux ScrubPony + Python
// at a glance
  1. Scrub a copy of a photo
  2. Run tests/verify_scrub.py
  3. Read the four checks
  4. Or do check 2 by hand
Prerequisites
  • A clone of the repository, for tests/verify_scrub.py
  • Python 3 and Pillow for checks 3 and 4; exiftool for check 1 (both optional)
// step 01

Scrub a photo

Use the default sibling output so you have both files side by side.

$ scrubpony photo.jpg
photo.jpg -> photo.scrubbed.jpg: removed 4 segments, 4944 bytes (49.2%), orientation preserved
// step 02

Run the verifier

It checks four things and exits non-zero if any of them fails.

$ python3 tests/verify_scrub.py photo.jpg photo.scrubbed.jpg && echo identical
identical
// step 03

Know what the four checks are

One: exiftool reports nothing from the drop list, and an EXIF block if present contains Orientation and nothing else. Two: the entropy-coded scan is byte-for-byte identical — this is the strong one. Three: both files decode to identical pixels. Four: both files look identical once EXIF orientation is applied, which is a separate claim, since a file can have byte-identical stored pixels and still appear turned a quarter turn.

// step 04

Do check 2 by hand if you prefer

If you would rather not run anybody's Python, this is a hex viewer and two hashes. Find FF DA — the SOS marker — in each file, take everything from that offset to the end, and compare the digests. The verifier itself deliberately locates that offset with its own segment scanner rather than asking ScrubPony where it thinks the scan starts, because using the tool under test to find the bytes that vindicate it would prove nothing.

$ tail -c +$OFFSET_ORIGINAL photo.jpg          | shasum -a 256
$ tail -c +$OFFSET_SCRUBBED photo.scrubbed.jpg | shasum -a 256

Verify it worked.

  • The verifier exits 0 and prints nothing alarming.
  • The two SHA-256 digests of the scan region match.
  • Opening both files side by side shows the same picture at the same orientation.
  • The scrubbed file is smaller by roughly the number of bytes the dry run predicted.

Common questions.

Some checks were skipped.

Expected. Check 1 skips without exiftool; checks 3 and 4 skip without Pillow. Check 2 — the byte-identity of the scan — needs neither and is the one that matters most.

Why is byte identity stronger than identical pixels?

Because identical pixels could in principle be produced by a decode-and-re-encode cycle at high quality. Identical compressed bytes cannot: nothing was recomputed.

What if a check fails?

That is a bug and a good one. Send the file to NorseHorse@norsehor.se or open an issue — a JPEG that breaks this is worth more than a description of how it breaks it.

Next steps.

Get ScrubPony

Strips identifying metadata out of JPEGs without touching a pixel. C99, no dependencies beyond libc, macOS and Linux, MIT-licensed.