Thumbnail encoding study shipped

Every grid thumbnail ends a chain of choices: format, quality, chroma subsampling, resolution. Here I run one photo through all of them with real byte counts, so you can see the tradeoffs instead of taking them on faith. The actual encoders the site uses (avifenc, jpegli, cwebp, sips) produced every number.

The verdict shipped: the live pipeline (holding/scripts/add-photos.sh) encodes every thumbnail as AVIF-primary + a jpegli q82 JPG fallback. That combination wins below, and it's why the site builds jpegli from source.

Format showdown

The same detailed color frame at 400×266px. PNG holds the lossless baseline; everything below it throws bits away. Eyeball the quality, then read the bytes. b/px = bytes per pixel, the size-density that actually scales.

PNG lossless178.7 KB1.72 b/px
JPG·sips q82 · 4:2:031.7 KB0.31 b/px
JPG·jpegli q60 · 4:2:011.0 KB0.11 b/px
JPG·jpegli q82 · 4:2:016.8 KB0.16 b/px
JPG·jpegli q95 · 4:2:034.5 KB0.33 b/px
WebP q60 · 4:2:07.8 KB0.07 b/px
WebP q80 · 4:2:011.8 KB0.11 b/px
AVIF q40 · 4:2:04.6 KB0.04 b/px
AVIF q63 · 4:2:010.4 KB0.10 b/px
AVIF q85 · 4:2:020.1 KB0.19 b/px
AVIF q63 · 4:4:411.3 KB0.11 b/px

Why the site builds jpegli from source

Look at the two q82 JPEGs above: system/sips lands at 31.7 KB, jpegli at 16.8 KB: same nominal quality, ~47% fewer bytes. Google's jpegli re-implements libjpeg and tunes it psychovisually; that win alone is why ~/.local/bin/cjpegli exists and the pipeline shells out to it instead of the OS encoder. AVIF beats both, but JPEG still backs up every <img> as the universal fallback, so shrinking it still pays off.

Grayscale: drop the chroma planes

A black-and-white Leica frame (400×267). In a grayscale image the two chroma planes carry almost nothing, so AVIF 4:0:0 (luma only) both encodes it honestly and rules out any faint color cast. Dropping to 4:0:0 saves barely any bytes over 4:2:0 because nothing lived in those planes to begin with. Correctness drives this, not size. The pipeline detects sips -g space → Gray and switches to --yuv 400.

PNG lossless51.0 KB0.49 b/px
JPG·jpegli q8210.4 KB0.10 b/px
AVIF q63 · 4:2:010.6 KB0.10 b/px
AVIF q63 · 4:0:010.5 KB0.10 b/px

Resolution scales bytes ~quadratically

The color frame at three long edges, AVIF q63 vs jpegli q82. Doubling the long edge roughly triples the bytes, and AVIF holds a steady ~35–38% lead over JPEG at every size, which is why the grid stays AVIF-primary and small and square.

resolutionAVIF q63jpegli q82AVIF saves
400×26610.4 KB16.8 KB38%
800×53333.3 KB54.1 KB38%
1200×80073.1 KB112.9 KB35%

What aadhar.sh actually ships