DEV Community

Lank_M
Lank_M

Posted on

Same 200 KB, three formats: why WebP and AVIF look cleaner than JPEG


At ImgIng I look after the client-side encoding path, and the question I get most about our quality defaults is why JPEG gets a higher number than WebP. For photos the table says WebP 75, JPG 80, AVIF 52. It looks backwards if you read quality as a universal dial. It isn't one, and the cleanest way I know to show that is to fix the byte budget and let each format spend it.

Same budget, three encoders

Each format was pushed to the highest integer quality that stays at or under 204,800 bytes (200 × 1024). JPEG and WebP came from the browser's own canvas.toBlob on an Apple M4 machine with 16 GB, running Chromium 149 built from open source. I used that path on purpose, since it's the one ImgIng (https://imging.ai/) takes for those two formats. AVIF is a different story. Chromium 149's toBlob('image/avif') quietly returned a 272-byte PNG, so the AVIF column comes from the AVIF encoder built into macOS (sips), not from a browser. In our product AVIF is an on-demand WASM encoder, but these numbers are not from it. PSNR is over RGB, SSIM is on luma with an 11×11 window.

Image Format Quality Bytes PSNR SSIM
Photo 1920×1080 JPEG 70 204,214 35.43 dB 0.9726
WebP 81 200,388 37.18 dB 0.9784
AVIF (sips) 69 203,578 37.99 dB 0.9842
Screenshot 1440×2400 JPEG 78 202,864 39.85 dB 0.9949
WebP 97 200,224 45.66 dB 0.9995
AVIF (sips) 96 200,493 45.20 dB 0.9997

The photo is a landscape wallpaper that ships with the OS, downscaled to 1080p. The screenshot is one of our own help pages, text on flat UI. On the photo WebP is 1.75 dB ahead of JPEG and AVIF 2.56 dB. On the screenshot the gap is 5.8 dB, and WebP and AVIF are close to level.

Text crop from the screenshot at the same ≤200 KB: original, JPEG q78, WebP q97, AVIF via sips

Look at the edges of the letters and the flat background right next to them. JPEG leaves a faint haze and some specks around each stroke. WebP and AVIF keep the background clean up to the edge. The crop is enlarged so the pixels are visible.

Why JPEG spends the same bytes worse

Baseline JPEG cuts the image into fixed 8×8 blocks and codes each one with a DCT. Apart from the DC term, a block knows nothing about its neighbours. A letter stroke is a sharp step, and a sharp step inside an 8×8 block spreads energy into the high-frequency coefficients. Those are exactly the ones quantization cuts first. What survives is the step plus ripples around it, which is the haze in the crop. It also pays for every flat block on its own, even a block that's pure white.

VP8, the lossy half of WebP, predicts each block from pixels it has already decoded above and to the left, and only codes the difference. On a flat UI background the prediction is nearly perfect, so the residual is close to zero and costs almost nothing. The bytes saved there go to the edges. It uses 4×4 transforms, so ringing stays in a smaller area, and it runs a deblocking filter inside the loop. AV1 takes the same idea further, with blocks that range from 4×4 up to 128×128, many more directional prediction modes, and extra filters (CDEF and loop restoration) after reconstruction. Large flat regions become a few very cheap blocks.

You can see that difference in the screenshot numbers. WebP could afford quality 97 on it while JPEG stopped at 78, and my reading is that WebP spent almost nothing on the background. I can't fully explain one detail: AVIF has the best SSIM on the screenshot but a slightly lower PSNR than WebP. My guess is that its post-filters nudge many pixels by a small amount while keeping the structure intact, which SSIM forgives and PSNR doesn't. I haven't isolated it, so it stays a guess.

What this means for a quality table

The quality numbers themselves don't carry across formats. At the same size the photo landed on JPEG 70, WebP 81 and AVIF 69, and the screenshot on 78, 97 and 96. That's why our table gives each format its own column and a separate row per content type: photo, smooth, texture and graphics/text, where graphics/text gets WebP 84, JPG 88, AVIF 60. The source comment says it was calibrated with SSIM measurements plus side-by-side viewing, and these results point the same way. All of this is one machine and two images, so I wouldn't treat the dB gaps as constants.

If you keep one quality setting and apply it to every output format, try the fixed-budget test above on two of your own images, one photo and one screenshot. Then give each format its own default.

Top comments (0)