JPEG forgets in eight-by-eight squares, and the arithmetic is on the page
"JPEG is lossy" is where most explanations start and stop. It is true and it is useless, because it does not say what is lost, or when, or how much. Those are all answerable, and the answers are arithmetic rather than opinion.
A JPEG encoder cuts the image into 8x8 squares, rewrites each square as a sum of 64 wave patterns, divides those 64 numbers by a table, and rounds. The rounding is the loss. Everything else is reversible.
This article follows one real 8x8 square the whole way through, then measures the mark the process leaves on the picture.
The table is the quality setting
The quality slider in every image editor does not control an algorithm. It scales a table of 64 divisors, and that table is stored in the file, so it can simply be read back out.
Here is the luminance table an encoder actually wrote at four different settings, pulled from the DQT marker of the resulting files:
quality 50 quality 75
16 11 10 16 24 40 51 61 8 6 5 8 12 20 26 31
12 12 14 19 26 58 60 55 6 6 7 10 13 29 30 28
14 13 16 24 40 57 69 56 7 7 8 12 20 29 35 28
14 17 22 29 51 87 80 62 7 9 11 15 26 44 40 31
18 22 37 56 68 109 103 77 9 11 19 28 34 55 52 39
24 35 55 64 81 104 113 92 12 18 28 32 41 52 57 46
49 64 78 87 103 121 120 101 25 32 39 44 52 61 60 51
72 92 95 98 112 100 103 99 36 46 48 49 56 50 52 50
Two things are worth noticing.
The quality-50 table is not an invention of the encoder. It is the example table printed in Annex K of the JPEG specification, reproduced digit for digit. Nearly every JPEG in the world is quantised with a scaled copy of a table published as an example in 1992.
And the scaling is plain arithmetic. Quality 75 is that table halved. Quality 25, measured the same way, is that table doubled exactly — 32, 22, 20, 32 against 16, 11, 10, 16. The documented rule is a scale factor of (100 - q) / 50 above quality 50 and 50 / q below it, and the files confirm it: the top-left divisor runs 2, 8, 16, 32 for qualities 95, 75, 50 and 25.
Look at the shape of the table rather than the numbers. Top-left is small, bottom-right is large. Top-left is the slow, broad variation in the square; bottom-right is the finest detail. The table says, in one picture, what JPEG believes: keep the broad shape, throw away the fine detail, and throw away more of it the lower the quality goes.
One square, taken apart
This is the busiest 8x8 square in one of this site's images — the highest-variance block in the file, which is to say the hardest case. It is a vertical edge: dark on the left, bright on the right.
27 20 16 122 254 239 247 247
21 26 12 86 249 247 250 245
22 24 14 59 248 250 246 248
25 21 19 57 249 250 242 249
25 24 13 73 252 248 246 245
26 22 10 117 254 241 248 245
28 16 40 189 254 239 247 248
26 13 88 244 248 245 248 246
The encoder subtracts 128 from every value, then applies the two-dimensional discrete cosine transform. The result is another 8x8 grid, but the numbers no longer mean brightness. Each one says how much of one particular wave pattern is present:
155.9 -781.3 -129.8 208.8 102.1 -76.9 -47.8 43.6
-56.2 -23.7 64.2 54.4 -31.8 -59.3 -0.4 35.8
56.0 22.0 -65.3 -56.1 35.7 62.9 -8.8 -40.3
-12.6 -5.1 9.1 17.1 12.7 -7.1 -19.1 -1.9
12.1 7.6 -11.5 -13.3 0.4 9.6 11.1 0.3
-0.4 -0.0 0.1 -0.9 10.1 1.0 0.2 -0.7
-0.3 0.3 0.2 -0.3 -0.3 0.3 0.6 0.8
0.6 -0.1 -0.2 0.4 0.8 -0.2 -0.6 0.1
The transform has not lost anything yet. Run it backwards and the original values come back. What it has done is sort the content: the top-left corner now holds almost all of the energy, and the bottom-right is nearly empty. That -781.3 is the single horizontal edge, described once.
This concentration is the whole trick, and it is why it works on photographs. In a photograph, neighbouring pixels are similar, so the fine-detail coefficients are small. In random noise they would not be, and JPEG compresses noise terribly.
Now divide by the quality-50 table and round:
10 -71 -13 13 4 -2 -1 1
-5 -2 5 3 -1 -1 0 1
4 2 -4 -2 1 1 0 -1
-1 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Thirty-nine of the sixty-four numbers are now zero. That is the compression: the encoder reads the grid in a zig-zag from top-left to bottom-right, hits a long tail of zeros, and stores "the rest are zero" in a few bits.
Reconstructing the square from what survived and comparing against the original: the worst pixel is off by 17 levels out of 255, and the average pixel is off by 5.3. At quality 75 the same square keeps 29 coefficients instead of 25, and the worst pixel is off by 15.
That is a hard edge — the case JPEG is worst at. Most squares in a photograph are far flatter and lose far less.
The grid it leaves behind
Everyone has seen JPEG blocking. It can be measured rather than described.
Take the brightness step between every pair of horizontally neighbouring pixels. Average the steps that cross an 8-pixel boundary, average the steps that fall inside a block, and divide. In an untouched image there is nothing special about every eighth column, so the ratio should sit at 1. Anything above 1 is the grid.
Measured on an image that had never been through a JPEG encoder:
source as-is ratio 1.025 (no grid, as expected)
quality 95 45,656 bytes ratio 1.138
quality 75 17,940 bytes ratio 1.361
quality 50 12,857 bytes ratio 1.573
quality 25 9,104 bytes ratio 2.127
quality 10 6,184 bytes ratio 3.154
The baseline of 1.025 is the check that makes the rest meaningful: the measurement finds no grid when there is no grid. Every row after it was produced by the encoder.
Alongside it, the share of 8x8 squares that come back completely flat — every pixel within one level of its neighbours, meaning every coefficient but the first was rounded away:
quality 95 0.9% of blocks flat
quality 75 12.1%
quality 50 30.9%
quality 25 56.0%
quality 10 70.7%
At quality 10, seven squares in ten are a single flat colour. That is not a loss of detail; it is a loss of the square.
The file that arrived with a grid already in it
The same measurement was run on a file that was already a JPEG before anything was done to it, and the baseline came back at 1.482 rather than 1.025. The grid was in the file on arrival, left by whichever encoder produced it.
Re-saving pushed it further: 1.508 at quality 95, 2.110 at quality 50, 3.515 at quality 10. A quality-95 save is usually described as near-lossless, and in terms of new damage it nearly is — but it is building on damage that is already there and cannot be removed.
This is the practical reason a converter cannot restore a JPEG. The information is not hidden, compressed or encrypted. It was divided, rounded and discarded.
Does every save really lose more?
The common warning is that each save degrades a JPEG further. Measured, that turns out to be true in one situation and false in another, and the difference is not the one most people expect.
Saving the same file eight times at the same quality, changing nothing else, and recording how much each save alters its own input:
save 1 17,940 bytes changed by 31
save 2 17,943 bytes changed by 6
save 3 17,931 bytes changed by 4
save 4 17,931 bytes changed by 2
save 7 17,931 bytes changed by 0
save 8 17,931 bytes changed by 0
It stops. By the seventh save the output is identical to its input and the file size has frozen. Almost all the damage happened on the first save, and after that the image is already a fixed point of its own quantisation table: divide, round, and the same numbers come back.
Now the same eight saves, with one pixel column cropped before each one so the 8x8 grid lands somewhere new in the content each time:
save 1 17,992 bytes changed by 33
save 2 18,377 bytes changed by 34
save 3 18,800 bytes changed by 32
save 5 19,559 bytes changed by 34
save 8 20,354 bytes changed by 31
It never stops. Every save does fresh damage, because the squares no longer line up with the ones that were quantised last time, and the blocking left by the previous generation is now interior detail that the new grid has to encode.
The file also grows — from 17,992 to 20,354 bytes across eight saves, while the image is getting smaller by a column each round. Thirteen percent more bytes for less picture, spent entirely on describing the previous encoder's artefacts.
So the rule is not "never re-save a JPEG". It is: re-saving costs nothing once the first save has happened, provided nothing moves the grid. Crop, resize, rotate by anything but a multiple of 90 degrees, or paste into a larger canvas, and the grid moves.
When these numbers do not apply
Flat graphics behave completely differently. The same blockiness test on an interface screenshot barely moved — 0.964 before, 1.073 at quality 50 — because 82% of its squares were already flat. The quantiser had almost nothing to remove. This is not JPEG performing well on screenshots; it is why JPEG should not be used for them at all. The damage lands on the few squares that carry the text, which is exactly where it is most visible.
The coefficients here are from the worst block in its image. It was chosen deliberately as the highest-variance square in the file. A typical photographic block loses far less.
Only luminance is shown. JPEG quantises colour with a second, coarser table, and usually throws away three quarters of the colour resolution before quantising at all through chroma subsampling. That is a separate mechanism and a larger loss on strongly coloured edges.
The quality numbers are not portable. Quality 75 is a libjpeg scale factor, not a standard. Another encoder's 75 may write a different table entirely, which is why the same number produces different files in different software.
The convergence result assumes identical settings. Same encoder, same quality, same subsampling, no edit. Change any of them and the second save is a first save again.
Checking it yourself
The quantisation table is not hidden. It sits in the DQT marker, which is the two bytes FF DB, followed by a length, a one-byte precision and table identifier, and then 64 values in zig-zag order. Find FF DB in a hex dump of any JPEG and the next 64 bytes after the header are the table.
If the first value is 16 and the second is 11, the file was written at quality 50 by a libjpeg-derived encoder. If it is 2 and 1, it was written at quality 95. The quality setting a file was saved at is recoverable from the file, long after whoever saved it has forgotten.
For the blocking measurement, you do not need code: zoom any heavily compressed JPEG to 800% and the grid is visible to the eye. The arithmetic above only turns that into a number so two files can be compared.
What this is for
The useful conclusion is not "avoid JPEG". It is that the loss has a shape, and the shape is predictable. It lands on fine detail, it lands hardest on hard edges, it arrives almost entirely on the first save, and it becomes permanent the moment the grid moves.
Which means the practical rules fall out of the arithmetic rather than folklore: keep an original that is not a JPEG, do the edits in one pass, and save once at the end. Not because saving is dangerous, but because every pass that moves the grid pays the first-save cost again.
Sources
- ITU-T T.81 / ISO-IEC 10918-1 — Digital compression and coding of continuous-tone still images
- ITU-T T.81 Annex K — Examples and guidelines (the quantisation tables)
- Independent JPEG Group — libjpeg, the reference implementation
Tools mentioned
← All articles · corrections: editorial policy