The guide
A quality setting is a knob, not a score: measure what the encoder actually threw away
JPEG 80 and WebP 80 are different promises from different machines, so the only honest way to pick a file size is to decode the result and measure it.
- 11 x 11 Gaussian window, standard deviation 1.5, in the SSIM definition
- MSE = 210 five distortions of one photo with one error and very different SSIM
- 30 to 50 dB typical PSNR for lossy 8-bit image compression
- 0.01 and 0.03 the two small constants K1 and K2 that keep SSIM stable
Read the full guide Fold the guide
Every export dialog that writes a lossy image offers a number. Quality 80. Quality 0.92. A slider from low to high. The number looks like a grade, and people treat it like one: 80 sounds safe, 60 sounds risky, 95 sounds wasteful. That reading is understandable and almost entirely wrong. The number is an instruction to one particular encoder about how hard to squeeze, and what it costs you depends on the picture, the format and the program that obeys it.
The useful question is never “what setting should I use”. It is “what is the smallest file that still looks the way I need it to look”, and that question has an answer only after the file has been made, decoded again and compared with the original. This page does exactly that, and the rest of this essay is about why the comparison has to be measured rather than assumed.
What lossy compression throws away
A lossy encoder saves space by discarding detail it predicts you will not miss. JPEG, standardised in 1992, transforms the colours into a brightness channel and two colour channels, cuts the picture into 8 by 8 blocks and describes each block with a discrete cosine transform. The quality setting decides how coarsely the frequency components are rounded. At a low setting the high frequencies are dropped altogether, and the rounding is the one step a decoder can never undo.
Colour usually goes first. Chroma subsampling stores the colour channels at a lower resolution than brightness, because human vision has lower acuity for colour differences than for luminance. In the common 4:2:0 scheme the colour channels keep half the horizontal and half the vertical resolution. Most photographs survive this without complaint. Thin red lettering on a blue ground does not.
WebP takes a different route. Its lossy mode descends from the VP8 video format and predicts each block from the blocks already decoded above and to its left, then stores only what the prediction got wrong. AVIF stores a still picture compressed with the newer AV1 video codec. All three throw information away, but they choose different information, so the same picture loses different things in each.
That is why a setting number cannot be carried from one format to another. JPEG 80 and WebP 80 are not two measurements on one ruler. They are two unrelated dials that happen to share a range from 0 to 100. Even for JPEG alone, that 0 to 100 scale belongs to a particular library, such as the one from the Independent JPEG Group, rather than to the format. The canvas specification that browsers follow says only that the quality argument is a number from 0.0 to 1.0 indicating the desired quality level; it does not say what any value must produce.
Measuring a difference: PSNR, and why it was not enough
The oldest way to compare a compressed picture with its original is to subtract them. Square every difference, average the squares and you have the mean squared error. Peak signal-to-noise ratio turns that into decibels: ten times the base-10 logarithm of the largest possible value squared, divided by the mean squared error. For 8-bit pictures the largest value is 255. Typical results for lossy image compression of 8-bit pictures run from 30 to 50 dB, and higher is better. Identical pictures have no error at all, so their PSNR is infinite, and an honest tool says so instead of printing a huge number.
PSNR is easy to compute and easy to check, which is a real virtue. Here is a worked example you can reproduce on paper. Add random noise with a standard deviation of 5 levels to a flat grey picture and round to whole levels. The squared error averages about 25 plus one twelfth for the rounding, roughly 25.08, so the PSNR is about 34.14 dB. The checks behind this page measured 34.13 dB on a 400 by 300 test picture, inside the sampling error the formula predicts.
The trouble is what PSNR cannot see. In their 2004 paper, Zhou Wang, Alan Bovik, Hamid Sheikh and Eero Simoncelli showed five distorted versions of one photograph of a boat, all with the same error: MSE = 210. One was brightened slightly. One had its contrast stretched. One was blurred, one compressed as JPEG, one sprinkled with impulse noise. To PSNR they are identical. To anyone looking at them they are not remotely alike: the brightened boat looks almost untouched, while the JPEG boat is visibly blocky.
Structure, not just error
The paper’s answer was the structural similarity index, SSIM. Its premise is that vision is tuned to extract structure from a scene, so a quality measure should ask how much of the local structure survived rather than how large the raw error is. It compares two small windows, one from each picture, by three things: their mean brightness, their contrast and the correlation of their patterns, which is the structure term.
The details matter if you want numbers that agree with anyone else’s. The paper uses an 11 x 11 circular Gaussian weighting window with a standard deviation of 1.5 pixels, normalised so its weights sum to one. Two small constants keep the division stable where a window is nearly flat: they are the squares of K1 times L and K2 times L, with K1 and K2 set to 0.01 and 0.03 and L, the dynamic range, equal to 255 for 8-bit values. The window slides one pixel at a time, giving an SSIM value for every position, and the mean of all those values is the score usually reported.
On the boat pictures the difference is stark. The mean-shifted boat scores 0.9900 and the contrast-stretched one 0.9168, while the JPEG version drops to 0.6949 and the blurred one to 0.7052. Same error, very different structure, and the ranking now matches what people see. Because television adopted it so widely, its four authors each received a Primetime Engineering Emmy in 2015.
Like most uses of SSIM, this page measures it on luma, the brightness signal formed as 0.299 of red plus 0.587 of green plus 0.114 of blue. Those weights come from the standard-definition television definition of Y’CbCr. They are applied to the gamma-encoded sRGB values a canvas hands over by default, the encoding the CSS colour specification defines, not to linear light. Per-channel SSIM is available as an option for pictures where colour carries the meaning.
Reading the map instead of the number
A single mean hides where the damage is. Because SSIM is computed for every window, it can be drawn as a map: white where a window kept its structure, dark where it did not. On a compressed photograph the dark patches sit along edges, in fine texture and around text, exactly where a viewer’s eye goes. A flat sky can be crushed to a fraction of its bytes and still read as white.
The map is the most practical part of the method. A picture with a mean SSIM of 0.97 can still hold one ruined logo, and the map shows it in a second. The difference map beside it is cruder, showing the largest change in any colour channel per pixel, but it confirms what changed and by how much. Neither replaces looking. They tell you where to look.
Choosing a target and checking by eye
Once every version has been measured, the decision becomes simple arithmetic. Pick a target SSIM, list every version from every format that meets it, and keep the smallest file. This page also refines the search: when the target falls between two ladder steps it encodes the settings in between, halving the gap, so the answer is not limited to the steps you happened to type.
The example picture on this page shows why the search should run across formats. Measured in a recent Chromium browser at a target of 0.970, no JPEG step on the default ladder reached it; JPEG at 95 scored 0.9678 at 119,177 bytes. WebP met it at a setting of 91 found by the refinement, with 79,564 bytes and an SSIM of 0.9715. Another browser ships other encoders, so expect other numbers; the page names the encoder it used.
The browser itself is part of the measurement. A canvas returns PNG when asked for a format it cannot encode, so the only reliable test of support is to encode a tiny picture and check the type that comes back. That is how this page decides whether AVIF is on offer; the Chromium build these checks ran in returned PNG when asked for AVIF. Some encoders also attach a colour profile to every file they write; the page strips it before measuring, so the bytes in the table are the bytes you download.
Now the limits, plainly. SSIM and PSNR are models of visible difference. They do not know how large the picture will be shown, how far away the viewer sits, or which part of it matters to you. The 2004 paper downsampled its test pictures by two before scoring, which this page does not do, so scores here can sit below scores from tools that copy that step. And no number certifies that nobody will ever see a difference.
So use the measurement to narrow the choice and your eyes to make it. Find the two or three smallest versions that meet the target, then compare them with the original at full size, on the screen your audience will use, around the faces, the lettering and the hard edges the map points to. If the smallest one passes that look, the setting number on it no longer matters. It was only ever a knob.
Sources
Every source consulted for this guide. Links checked October 30, 2026.
- Image Quality Assessment: From Error Visibility to Structural Similarity IEEE Transactions on Image Processing 13(4), 2004; Wang, Bovik, Sheikh and Simoncelli (authors' reprint)
- Structural similarity index measure Wikipedia
- Peak signal-to-noise ratio Wikipedia
- JPEG - Wikipedia Wikipedia
- WebP - Wikipedia Wikipedia
- AVIF - Wikipedia Wikipedia
- Chroma subsampling Wikipedia
- YCbCr - Wikipedia Wikipedia
- HTML Standard: 4.12.5 The canvas element WHATWG
- CSS Color Module Level 4 W3C
- HTMLCanvasElement: toBlob() method MDN Web Docs
- OffscreenCanvas: convertToBlob() method MDN Web Docs
- OffscreenCanvas MDN Web Docs
- Window: createImageBitmap() method MDN Web Docs
- WebP Container Specification Google for Developers