Files
booth/persistent-memory.d/2026-09-23-thumbnails-sized-for-the-tile.md

1.9 KiB

Thumbnails sized for the tile's width at 2x, not 512 on the long side

2026-09-23. Operator on sindra-nude-final: "the images look blurry until they're selected and blown up." Commits c2b1454, c19d8c9, merged 1d31ab0.

The measurement

  • The cap was 512px on the LONGEST side. Tiles are sized by WIDTH (width:100%; height:auto).
  • Chromium put desktop tiles at 321-361 CSS px (3 columns, 1440px viewports and up), 324-472 at 2 columns, and up to 650 at 1 column (measured across a 360-2560 viewport sweep).
  • A 704x1408 portrait got a 256-wide thumbnail: stretched 1.4x at 1x density and 2.8x on a 2x screen.
  • The live sizes are mostly 704x1408, 896x1216, 832x1216 and 1024x1024 portraits (368 images sampled).

The rule

  • THUMB_WIDTH = 768 (2x the widest desktop tile) and THUMB_HEIGHT_MAX = 4096.
  • An original that fits is served as-is only when it's also light (<=64 KB; 768-wide thumbnails average 39 KB) or animated.
  • tests/test_thumbs_browser.py binds 768 to the rendered grid at 1440, 1920 and 2560.
  • Cost across all 381 live images: 4.8 → 14.2 MB at 768; 1024 would have been 18.5 MB. Live rebuild: 14.5 MB, 369 webp and 12 originals, 9 s.
  • The operator kept 768 (2026-09-24).

heid bug-hunt (4/4, five seat-executed probes) → c19d8c9

  • A cache hit must be a REGULAR file with its source's EXACT mtime. A planted directory was served as the thumbnail, and cp -p pinned stale ones forever.
  • The cache dirs are made component by component without following links. A .thumbs link put the cache outside the booth.
  • The temp file is mkstemp. <out>.<pid>.tmp was plantable as a link: 600 B became 316,400 B.
  • Palette transparency survives. This one was INTRODUCED by c2b1454's fits-but-heavy branch.
  • EXIF orientation is honoured.
  • A 64 MP decode budget.
  • The whole rule is in the cache name: .768x4096q78v2.webp.