PassRealPricingApp

How JPEG quantization tables identify the device that wrote a file

Every JPEG stores its quantization tables in the file header, because a decoder needs them to reconstruct the image. Camera manufacturers use tables specific to their bodies and firmware, distinct from the reference table in the JPEG standard that most software libraries use. Reading the table therefore narrows down what wrote the file, independently of anything EXIF claims.

Naturalization before and after on a generated image, full frame with the same region enlarged at two magnifications
Source: ai-sdxlt-03.png, 1024×1024. After: JPEG, Apple iPhone 15 Pro EXIF, Apple (mesurée) quantization table. SSIM 0.8897, PSNR 32.5 dB. Full image on both sides, then the same detail at 100 % zoom and 200 % zoom.

What the tables are for

JPEG compresses by transforming each 8x8 block of pixels into frequency coefficients, then dividing those coefficients by a table of divisors and rounding. Larger divisors throw away more information. The high-frequency coefficients, which the eye is least sensitive to, get the largest divisors.

The decoder cannot reverse this without knowing the divisors, so they travel with the file in the DQT marker. Two tables are typical: one for luminance, one shared by the chrominance channels, each holding 64 values.

That is the entire mechanism. The forensic value is a side effect of the format needing to be self-describing.

Why the values differ between devices

The standard includes an example table in its informative Annex K. It is an example, not a mandate, and it was derived from perceptual experiments decades ago.

Manufacturers derive their own instead, tuned against their own sensors, their own demosaicing and their own noise characteristics, and adjusted for the quality settings they expose in the menu. Firmware updates change them. Phone makers running computational pipelines produce different tables again, because the image reaching the encoder has already been through more processing.

Software libraries, meanwhile, scale the Annex K table by a quality factor. This is what libjpeg does, which means it is effectively what Pillow, most editors and most upload pipelines do.

Reading the table on a file

The interesting comparison is rarely the table alone. It is the table against the EXIF. Agreement means the file's compression is consistent with its claimed origin. Contradiction means something re-encoded it, which may be an editor, an upload pipeline, or a claim that was never true.

What the table cannot tell you

The signal is real and it is narrow, and overreading it is easy.

What survives all those caveats is the comparison with EXIF. A file whose table and whose claimed body disagree has been through something, and knowing that is useful even when it does not say what.

Why this matters for generated images

An image produced by a model and saved by a Python library carries the library's scaled Annex K table. Writing camera EXIF onto that file produces a contradiction: metadata claiming a specific body, compression matching a generic software encoder.

The pipeline behind this site avoids that by writing the measured table for the make it declares. Where no measured table is available for a make, it falls back to the scaled standard table and declares accordingly, because a table that contradicts the claim is a louder signal than a generic one.

The sensor and frequency stages run before this: grain at intensity 0.018, lateral chromatic aberration reaching 1.25 px at the corners, and a low-pass filter at 0.88 of Nyquist. The encode is the last thing that happens, so everything upstream is what gets compressed.

What is checkedValue
Accepted formatsPNG, JPEG, WebP
Maximum size20 MB
Maximum dimension8192 px on the longest side
Sensor grain intensity0.018
Lateral chromatic aberration1.25 px at the corners, none at the centre
Frequency cutoff0.88 of Nyquist

Questions

Where is the table stored?

In the DQT marker segment, before the scan data. There are usually two tables, one for luminance and one for chrominance, each 64 values arranged for an 8x8 block. `djpeg -verbose` and `exiftool -htmldump` both display them.

Why do manufacturers use different tables?

Because the standard's example table is a starting point, not a requirement. Manufacturers tune their own against their own sensors and processing, trading file size against the artefacts their pipeline produces, and firmware versions change them.

How specific is the identification?

It narrows, rather than pinpoints. Tables are shared across bodies in a range and across firmware versions, so a match indicates a family. Combined with the EXIF make and model, agreement or contradiction between the two is what carries the information.

What does a library-encoded file look like?

It carries a scaled version of the standard's Annex K table, which is what libjpeg produces at a given quality setting. That is normal for anything exported by software, and abnormal for a file whose EXIF claims it came straight out of a camera.

Does resaving a camera JPEG destroy this?

Yes. Re-encoding writes the new encoder's tables, so a camera file edited and exported by an image editor carries the editor's tables and the camera's EXIF. That mismatch is extremely common and innocent, which limits how much weight the signal can carry.

Limits

Naturalization operates on the pixels and on the file, not on the content of the image. A subject that is implausible - six fingers, inconsistent reflections, text that does not read - stays implausible after processing, and a human reviewer will notice it. PassReal changes what a statistical classifier measures, not what a person sees.

Results vary by generator, by subject and by detector, and detectors are retrained. No pass rate is published on this page because none has been measured in a way that would still hold next month.

Process three images free

Three images, no card, no expiry.