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.
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
djpeg -verbose -verbose file.jpg > /dev/nullprints both tables.exiftool -htmldump file.jpgshows the marker structure with the DQT segment expanded, which is easier to read when comparing two files side by side.- Published databases map tables to device families, and searching a table's first row is usually enough to find the family it belongs to.
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.
- It identifies an encoder, not a photographer. A camera file opened in an editor and exported carries the editor's tables, which is the normal outcome of ordinary editing rather than evidence of anything.
- Tables are shared. A single table may belong to a whole product line across several years, so a match indicates a family and not a serial number.
- Phone pipelines complicate it further. Computational photography re-encodes along the way, and what reaches storage may not carry the tables the sensor's own encoder would have used.
- Chat applications re-encode on upload. An image received through a messaging app carries that app's tables regardless of where it started.
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 checked | Value |
|---|---|
| Accepted formats | PNG, JPEG, WebP |
| Maximum size | 20 MB |
| Maximum dimension | 8192 px on the longest side |
| Sensor grain intensity | 0.018 |
| Lateral chromatic aberration | 1.25 px at the corners, none at the centre |
| Frequency cutoff | 0.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.
Three images, no card, no expiry.