Image Compression

JPEG Quality Settings Explained: What the Number Actually Means

Quality 80 is not 80% of anything. It is an index into a quantisation table. Measured on one photograph: dropping from 100 to 90 removes 77% of the file and 4.2 dB of fidelity; dropping from 40 to 30 removes 17% and costs almost as much.

Ahtisham Khan

Developer and semantic SEO practitioner

Published
Last updated
Updated
Reading time
8 min read

The JPEG quality number is an index into a quantisation table. It is not a percentage of the image that survives. Quality 80 does not keep 80% of the picture, and quality 50 does not discard half of it. The number scales one step of the encoder, and the relationship between that setting and the resulting file size is steeply non-linear.

The figures below come from a single 1280 × 854 photograph encoded at twelve quality levels by two encoders, with fidelity measured against the uncompressed original. The measurement method and its limits are described at the end.

What the quality number controls

JPEG divides an image into blocks of 8 × 8 pixels. It converts each block from pixel values into 64 frequency coefficients using a discrete cosine transform. The first coefficient holds the average brightness of the block. The other 63 describe progressively finer detail.

The transform itself loses almost nothing. Quantisation is the lossy step. Each coefficient is divided by a value from a quantisation table and rounded to a whole number. Large divisors round many coefficients to zero, and long runs of zeros cost almost nothing to store. The file shrinks in proportion to how many coefficients were zeroed.

The quality setting scales that table. A low number produces large divisors, more zeros and a smaller file. A high number produces small divisors, fewer zeros and a larger file. That is the whole mechanism. Nothing in it corresponds to a percentage.

The scale is not standardised

The JPEG specification defines the quantisation process. It does not define the tables. Each encoder ships its own and maps the 0 to 100 scale onto them differently.

The effect is large. At quality 80 the test photograph came out at 67.5 KB from libjpeg-turbo and 41.1 KB from MozJPEG. Both files carry the label "quality 80". One is 39% smaller than the other. A quality number is therefore only meaningful alongside the encoder that produced it, and comparing quality numbers between two tools tells you nothing useful.

How file size responds to the quality setting

Size falls fastest at the top of the scale, where the encoder is spending large numbers of bits on coefficients that contribute almost nothing visible.

Qualitylibjpeg-turboMozJPEGBits per pixelSaved vs. previous step
100589.8 KB549.4 KB4.42
95254.2 KB169.0 KB1.9157%
90136.7 KB88.7 KB1.0346%
8591.6 KB53.7 KB0.6933%
8067.5 KB41.1 KB0.5126%
7551.1 KB31.5 KB0.3824%
7042.1 KB25.3 KB0.3218%
6030.3 KB19.7 KB0.2328%
5024.8 KB16.5 KB0.1918%
4020.6 KB14.0 KB0.1617%
3017.2 KB11.2 KB0.1317%

Between quality 100 and quality 90 the file lost 77% of its size. Between quality 40 and quality 30 it lost 17%. The top of the scale is where the savings are, and the bottom of the scale is where the damage is.

What each step costs in fidelity

Peak signal-to-noise ratio measures how far the decoded pixels have drifted from the original. Higher is closer. The scale is logarithmic, so a difference of 3 dB represents a halving of the error.

QualitySize (libjpeg-turbo)PSNRSize lost vs. 100Fidelity lost vs. 100
100589.8 KB43.76 dB
95254.2 KB40.83 dB57%2.93 dB
90136.7 KB39.56 dB77%4.20 dB
8591.6 KB38.82 dB84%4.94 dB
8067.5 KB38.21 dB89%5.55 dB
7042.1 KB37.52 dB93%6.24 dB
6030.3 KB37.09 dB95%6.67 dB
5024.8 KB36.78 dB96%6.98 dB
3017.2 KB35.74 dB97%8.02 dB

Read the last two columns together. Moving from quality 100 to quality 90 gives up 4.2 dB and removes 77% of the file. Moving from quality 90 to quality 80 gives up a further 1.35 dB and removes another 51%. Moving from quality 40 to quality 30 gives up 0.59 dB and removes only 17%.

The first trade is excellent. The last is poor: it costs measurable fidelity and returns very little. Quality 100 is the worst setting on the scale for any purpose other than archival, because it spends four times the bytes of quality 90 for a difference no viewer will see.

What PSNR does not tell you

PSNR measures arithmetic distance between pixels. The human visual system does not. A 1 dB drop concentrated in a smooth sky is obvious; the same drop spread across dense foliage is invisible. Treat the PSNR column as a consistency check across settings on one image, not as a score of perceived quality. Judge the image with your eyes at the size it will be displayed.

What each quality range is for

95 to 100
Visually indistinguishable from the source and very large: 254 KB to 590 KB for a 1.09-megapixel photograph. Correct for a master copy that will be edited again. Wasteful on a web page.
85 to 95
Excellent quality with a real saving, 92 KB to 254 KB on the test image. Use it for photography that matters, images that may be printed, and pictures with fine texture such as fabric, hair or foliage.
75 to 85
The web default, 51 KB to 92 KB here. Artefacts exist in the file but are invisible at normal viewing distance. Almost every image on a website belongs in this band.
60 to 75
Softening becomes visible in smooth gradients: skies, skin, out-of-focus backgrounds. Acceptable for thumbnails and decorative backgrounds.
Below 60
Visible blocking and ringing, and diminishing returns on size. Below quality 40 each further step removed under 20% of the file. Use it for placeholders, not finished work.

Image content changes the correct setting more than the setting does

The quality number is not the largest variable. Content is. Four images of identical dimensions were encoded at quality 80 by the same encoder.

ContentJPEG at quality 80PSNRSame image as PNG
Random noise680.7 KB12.57 dB3209.1 KB
Photograph67.5 KB38.21 dB1274.1 KB
Flat graphic, hard edges15.4 KB42.72 dB14.6 KB
Smooth gradient10.1 KB50.82 dB23.0 KB

The same encoder at the same setting produced files 67 times apart in size. Noise is the pathological case: every 8 × 8 block is unpredictable, so almost no coefficient quantises to zero, and the result is both enormous and badly damaged at 12.57 dB. A smooth gradient is the opposite: nearly all the energy sits in the first few coefficients, so the file is tiny and nearly perfect.

The practical consequence is that a fixed quality setting produces wildly variable file sizes across a batch. If you need a predictable output size, set a target size and let the encoder search for the quality that meets it, rather than fixing the quality and hoping.

Chroma subsampling costs more than several quality points

JPEG stores brightness and colour separately. Human vision resolves brightness far more finely than colour, so most encoders store colour at half resolution in each direction. That is 4:2:0 subsampling. Storing colour at full resolution is 4:4:4.

Quality4:2:04:4:4Cost of full colour resolution
7551.1 KB63.0 KB+23%
8591.6 KB111.0 KB+21%
95254.2 KB298.1 KB+17%

Keep 4:2:0 for photographs. Switch to 4:4:4 only for images with saturated colour against hard edges, where subsampling produces coloured fringes: red text on white, logos, and screenshots of coloured interface elements. Those images are usually better served by PNG or WebP anyway.

Progressive encoding is close to size-neutral

A baseline JPEG stores the image in a single top-to-bottom pass. A progressive JPEG stores it in several passes of increasing detail, so a partially downloaded file renders as a complete but soft image.

On the test photograph, progressive encoding produced a file 0.5% larger at quality 75 and 2.2% smaller at quality 85. The size difference is negligible in both directions. Choose progressive for perceived loading behaviour on slow connections, not for file size.

Re-saving at the same settings changes very little

The common warning is that every re-save of a JPEG degrades it further. The test qualifies that. The photograph was encoded at quality 80, then re-encoded from the result nine more times at the same setting and the same dimensions.

GenerationSizePSNR vs. original
167.5 KB38.21 dB
267.5 KB38.17 dB
367.5 KB38.15 dB
567.5 KB38.14 dB
1067.5 KB38.13 dB

Ten generations cost 0.08 dB in total. The reason is that quantisation is close to idempotent: once a coefficient has been rounded to a multiple of its divisor, rounding it again by the same divisor leaves it unchanged. The image converges after the first pass.

The warning still holds in the situation that actually occurs. Loss compounds when something changes between saves. Cropping or resizing shifts the 8 × 8 block grid, so a different set of coefficients is quantised each time. Lowering the quality on any save applies a coarser table. Editing brightness or colour moves every value before it is re-quantised. Keep an untouched original, edit from it, and export once.

Which quality to use for each job

JobQualitySubsamplingReason
Content image on a web page804:2:0Best size-to-fidelity trade on the curve above
Hero or full-width image82 to 854:2:0Viewed larger, so artefacts have more room to show
Thumbnail under 400 px70 to 754:2:0Displayed small; detail is discarded by the display anyway
Photograph for email80 after resizing4:2:0See the note on resizing below
Image that will be edited again95 or PNG4:4:4Preserves headroom for a second encode
Print submissionDo not compressSupply the original file

One setting outranks all of these. Resizing the image to the dimensions it will actually be displayed at saves more than any quality adjustment. The same photograph at quality 80 was 67.5 KB at full width and 16.4 KB at half width, while dropping the quality to 40 at full width produced 20.6 KB. The resized file is both smaller and visibly better. Reduce the pixel dimensions first, then set quality 80.

How these numbers were measured

Source: one photograph, 1280 × 854 pixels, 1.09 megapixels, held as a lossless PNG and decoded once into raw RGB as the reference.

Encoders: libvips 8.17.3 through sharp 0.34.5, using libjpeg-turbo for the baseline JPEG column, MozJPEG for the MozJPEG column, and libwebp 1.6.0 where WebP is mentioned. PSNR was computed over all three colour channels against the raw reference. Sizes are the exact byte lengths of the encoded files, converted at 1024 bytes per kilobyte.

Limits worth stating plainly. One photograph is not a benchmark suite, and a different image will move every number in the tables, though the shape of the curve holds across photographic content. The noise, flat-graphic and gradient images are synthetic and chosen to mark the extremes rather than to represent typical content. PSNR is a weak proxy for perceived quality, as noted above.

One difference applies to the compressor on this site. It encodes through the browser Canvas API, which exposes no MozJPEG option, so its output sits closer to the libjpeg-turbo column than the MozJPEG one. That costs a few percent in file size and buys the guarantee that the image never leaves your device.

From the blog

Other guides you may find useful.

  • Practical Guides

    How to Compress Images for a Website Without Wrecking Them

    Resize before you compress. Measured on one photograph: half the width at quality 80 produced a 16.4 KB file, while full width at quality 40 produced 20.6 KB and looked far worse. The order of operations matters more than the settings.

    8 min read

  • Image Formats

    WebP vs JPEG: Which Should You Use, and When JPEG Still Wins

    WebP produced a 27.0 KB file against MozJPEG's 41.1 KB on the same photograph at slightly higher measured fidelity — 34% smaller. It also produced a larger file than JPEG on random noise. The advantage is real and content-dependent.

    9 min read

  • Image Formats

    PNG vs JPEG: When to Use Each, With the File Sizes to Prove It

    PNG stored the same photograph in 1274.1 KB where JPEG needed 67.5 KB — nineteen times larger. On a flat graphic PNG won. On a smooth gradient PNG lost to JPEG by a factor of two, which surprises most people.

    9 min read