“Lossy compression discards detail you will not notice” is the sentence every explanation offers, and it raises the obvious question it never answers: how does a piece of software know what you will not notice?
The answer is a genuinely clever piece of engineering, and understanding it makes several practical decisions obvious.
Step one: separate brightness from colour
The first thing a JPEG encoder does is stop thinking in red, green and blue. It converts the image into one luminance channel — brightness — and two chrominance channels carrying colour.
This is done because human vision is markedly better at brightness than at colour. Our eyes have far more receptors for light level than for hue, which means fine detail in colour information can be reduced substantially before anyone notices, while the same reduction in brightness is obvious immediately.
So the encoder throws away colour resolution straight away, typically storing colour at half resolution horizontally and vertically — a quarter of the samples. That alone removes half the data before any real compression has happened, and it is almost invisible on a photograph.
It is not invisible on a red logo against a white background, which is a hint about what is coming.
Step two: describe the image as waves
The image is cut into 8×8 blocks, and each block goes through a discrete cosine transform.
The idea is easier than the name. Instead of storing sixty-four brightness values, the DCT describes the block as a combination of sixty-four patterns — from a flat, even tone, through gentle gradients, up to fine alternating checkerboards. Each pattern gets a coefficient saying how much of it is present.
No information is lost here. It is a change of description, entirely reversible. But it sorts the block into something extremely useful: the low-frequency coefficients at one end describe broad, smooth variation, and the high-frequency ones at the other describe fine, rapid detail.
Step three: this is where the loss happens
Now quantisation. Every coefficient is divided by a value from a table and rounded to a whole number.
The table is not uniform. Low-frequency coefficients are divided by small numbers, so they survive nearly intact. High-frequency coefficients are divided by large numbers — and once rounded, most of them become zero.
That is the loss. Not blurring, not averaging: fine-detail coefficients rounded to nothing.
And now the last piece falls into place. A block of sky, skin, or foliage is mostly smooth variation, so almost all its energy is in the low frequencies. Zeroing the high frequencies costs very little. Meanwhile a run of zeros compresses to almost nothing, which is where the dramatic size reduction actually comes from.
The quality setting is the quantisation table. A lower quality means bigger divisors, more coefficients rounded to zero, a smaller file, and more visible damage.
Why text and logos suffer
A hard black-to-white edge is not smooth variation. Reproducing a sharp edge requires the high-frequency patterns — precisely the ones quantisation destroys first.
Zero them and the edge cannot be reconstructed cleanly. What comes back is the encoder’s best approximation from the surviving low-frequency components, which overshoots and undershoots around the transition. That is the grey halo you see around text in a JPEG screenshot, and the mottling in flat areas of colour.
This is why the format guidance is what it is. It is not a stylistic preference. Lossy compression is built on an assumption about the content, and text violates it.
Why re-saving compounds
Each encode quantises. Decode a JPEG and you get pixels reconstructed from already-quantised coefficients — an approximation. Encode again and the encoder quantises that, discarding detail from an image that has already had detail discarded.
The damage is not simply doubled. The second pass works on the artefacts of the first, blocking on blocking, and errors accumulate at block boundaries that no longer align with anything in the original image.
Which produces the one habit worth forming: keep an original and export copies. Never let a lossy export overwrite the file it came from, and never edit-save-edit-save a JPEG in place.
Why the quality curve is so uneven
The relationship between the quality number and file size is sharply non-linear, and it has a practical consequence people rarely exploit.
Going from 100 to 90 typically halves the file at almost no visible cost, because at quality 100 the encoder is faithfully preserving high-frequency coefficients that contribute nearly nothing perceptually — expensive to store, invisible to you.
Going from 90 to 80 saves less and costs a little more. Going from 70 to 60 saves very little and costs a great deal, because by then quantisation is eating coefficients that were doing real work.
Most of the available benefit is in that first step. Which is why exporting at 100 is almost always the wrong choice — you are paying double for something nobody can see.
Why a file sometimes grows
Re-compressing an already-compressed JPEG can produce a larger file, which surprises people.
The reason is that the first encode already removed the redundancy. What remains — including its own blocking artefacts — is close to noise, and noise does not compress. The second encoder finds little to remove while adding its own container overhead, and can end up bigger than what it started with.
Our compressor handles this explicitly: if the re-encode produces something larger than the original, it keeps the original and says so on the row. That guard exists because the alternative — silently returning a bigger file and calling it compressed — is a tool lying to you. Across two test photographs we saw 2.36 MB come down to 37.8 KB, a 98% reduction; the guard is for the cases where that does not happen.
The short version
- Colour resolution goes first, and you will not miss it on a photograph
- Fine detail is stored separately from broad shapes, then rounded away
- Photographs are mostly broad shapes, so this is cheap
- Text is mostly fine detail, so this is ruinous
- Every re-save runs it again on damaged input
- Quality 85–90 gets nearly all the benefit; 100 wastes space and 60 wastes quality
Where WebP and AVIF differ
The framework above is JPEG’s, and it is worth knowing what the newer formats changed, because the practical advice shifts slightly.
WebP’s lossy mode derives from video compression. Rather than transforming every block independently, it predicts each block from its already-decoded neighbours and encodes only the difference between the prediction and reality. Since adjacent parts of an image are usually similar, the difference is small, and small differences compress better than whole blocks.
This is why WebP is meaningfully smaller than JPEG at comparable quality — it is not quantising more aggressively, it is having less to encode in the first place.
AVIF takes the same idea considerably further, with more prediction modes, variable block sizes and a more capable transform, which is why it wins again at the low end where JPEG falls apart.
Two practical consequences. First, the quality numbers are not comparable across formats — quality 80 in WebP is not quality 80 in JPEG, and the same number produces different results. Judge by looking, not by matching numbers. Second, all of them share the fundamental property: they are lossy, the loss is permanent, and re-encoding compounds it. Converting a JPEG to WebP does not undo the JPEG’s damage. It adds a second round on top.
The habit that protects you is identical regardless of format, which is the useful thing about understanding the mechanism rather than the file extensions: keep the original, export copies, and never let a lossy file overwrite the thing it came from.
Compress images in your browser, with a guard against files that would get bigger, using our image compressor. Nothing is uploaded.
