Skip to content

Downscale captures too large for the browser to render#54

Merged
jeremyfelt merged 1 commit into
trunkfrom
feat/downscale-oversized-captures
Jun 26, 2026
Merged

Downscale captures too large for the browser to render#54
jeremyfelt merged 1 commit into
trunkfrom
feat/downscale-oversized-captures

Conversation

@jeremyfelt

Copy link
Copy Markdown
Member

Problem

Browsers refuse to decode an image taller or wider than 32,767px (Skia's kMaxDimension) and render it as a broken/corrupt image — the console reports the image as corrupt. Full-page mobile captures cross this routinely: a narrow viewport stacks content into a very tall page, and a deviceScaleFactor of 2 doubles the pixel height again. The capture PNG on disk is valid; only the browser viewing the report can't paint it, so some screenshots silently fail to load in the report.

What this does

  • src/downscale.mjs (new) — an area-filter (box-average) resampler, plus displayDimensions (clamp the longest side to the limit, keep aspect ratio) and downscaleToDisplay. Area averaging keeps shrunk text and 1px borders legible.
  • compare writes a downscaled copy of any oversized image to a new .reglance/display/ directory and points the report at it. pixelmatch still runs at full resolution against the originals, and the promoted baseline in controls/ is never modified — only the displayed copy is shrunk.
  • Comparison view shows a "Downscaled" banner with the original and shown dimensions whenever an image on screen was shrunk (mode-aware: diff mode reports the diff image's numbers).
  • capture warns at screenshot time when it writes a PNG past the limit — read straight from the IHDR header (a 24-byte read, no full decode) — so the cause is visible before the report is built.

Why downscale on display rather than at capture

Keeping the full-resolution capture as the source of truth means pixel diffs stay accurate and the baseline isn't perturbed by a height change crossing the limit. Only the report's rendered copy is shrunk.

Test plan

  • npm run lint — clean
  • npm test — 124 pass. New coverage for the resampler (flat-color and boundary averaging), displayDimensions clamping/aspect-ratio/guards, the PNG header reader, and the report linking display copies + surfacing scaled.
  • Verified end-to-end against a real project whose home-mobile capture was 34,162px tall: it now gets a 748×32767 display copy, the report links it, the banner renders, and pages under the limit are untouched.

🤖 Generated with Claude Code

Browsers refuse to decode an image past ~32,767px on a side (Skia's
kMaxDimension) and show it as a broken/corrupt image in the report.
Full-page mobile captures cross this routinely: a narrow viewport stacks
content into a very tall page, and a 2x deviceScaleFactor doubles the
pixel height again. The PNG on disk is valid — only the browser viewing
the report can't paint it.

- New src/downscale.mjs: an area-filter (box-average) resampler plus
  helpers to compute display dimensions and shrink an oversized PNG.
- compare writes a downscaled display copy to a new .reglance/display/
  directory for any image over the limit and points the report at it.
  pixelmatch still runs against the full-resolution originals, and the
  promoted baseline is never modified.
- The comparison view shows a "Downscaled" banner with the original and
  shown dimensions whenever an image on screen was shrunk.
- capture warns at screenshot time when it writes a PNG past the limit
  (read straight from the IHDR header, no full decode), so the cause is
  visible before the report is built.

Adds tests for the resampler, the display-dimension math, the PNG header
reader, and the report's display/scaled wiring.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@jeremyfelt jeremyfelt merged commit f150607 into trunk Jun 26, 2026
2 checks passed
@jeremyfelt jeremyfelt deleted the feat/downscale-oversized-captures branch June 26, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant