ComparePicture

Why identical-looking JPEGs have pixel differences

Recompression, chroma subsampling, colour profiles and resampling all change pixels you cannot see. How to tell them apart from real edits.

Every save is a new approximation

JPEG does not store pixels. It stores an approximation of each 8×8 block as a set of frequencies, rounds those frequencies according to a quantisation table, and throws away what rounds to nothing. Decoding rebuilds the block from what is left. Save the result again — even at the same quality — and the rounding happens again on slightly different numbers, so the pixels move by a level or two. Two files of the same photograph from two apps will almost never match pixel for pixel.

The usual suspects

  • Quality setting. A lower quality uses coarser quantisation. ComparePicture estimates each file’s setting from its own tables and shows both in the Quality and Metadata views.
  • Chroma subsampling. 4:2:0 stores colour at a quarter of the resolution of brightness; 4:4:4 does not. Red text on blue is where you see it.
  • Colour profiles. The same numbers mean different colours under Display P3 and sRGB. A file that lost its profile is converted differently.
  • Resampling. A resize, even a round trip to the same size, filters every pixel.
  • Orientation. A phone photo may be stored sideways with an EXIF flag saying how to turn it. Tools that ignore the flag compare a rotated picture. ComparePicture applies it, and says so in the metadata table.

Telling noise from an edit

Recompression noise is spread thinly over the whole picture and concentrated on edges; an edit is concentrated in one place. So: compare with threshold 0 and the changed-pixel count is high; raise the threshold to around 0.1–0.2, or pick the Photo preset with its small blur, and the noise drops out while a real edit stays as a region. The heatmap in the image diff view shows the difference at a glance: an even fog is compression, a bright patch is a change.