Summary
Proposal: an optional imageScale report field so the in-catalog page image can be captured at a device's native pixel density while boxIDs stay in CSS pixels.
shoot.js currently captures with scale: 'css' — one image pixel per CSS pixel regardless of the emulated device. For scans that emulate high-DPR devices (iPhone DPR 3, common Android profiles at fractional DPRs like 2.625), the page image is a downsample of what the device would actually render, and it looks soft when displayed on high-DPI screens.
Proposal
When report.imageScale > 1:
- launch the catalog's browser context with
deviceScaleFactor: report.imageScale, and
- capture the page image with
page.screenshot({scale: 'device'}) instead of 'css'.
The image then has imageScale × the pixels of the CSS layout, while getBoundingClientRect (and therefore every catalog boxID) remains CSS-pixel by definition — consumers map coordinates onto the image by multiplying by imageScale. Omitted or 1 keeps today's behavior byte-identical.
Two implementation notes from testing this in production:
- A Playwright context
deviceScaleFactor cleanly overrides the --force-device-scale-factor=1 launch arg used for chromium head emulation, and rect values are unaffected — verified empirically.
- Fractional scales work exactly: a 2.625 capture of a 1280-CSS-px page yields a 3360-pixel-wide image (1280 × 2.625), boxIDs unchanged.
A natural policy for callers (ours): set imageScale to the scan device's own windowOptions.deviceScaleFactor, so the page image is what the emulated device natively renders and the catalog page's DPR matches the test pages' (same srcset / image-set resource selection).
Scope: only getCatalog's launch and shoot() call sites change; test acts and their launches are untouched. We're running this as a patch in production; happy to submit a PR.
Summary
Proposal: an optional
imageScalereport field so the in-catalog page image can be captured at a device's native pixel density whileboxIDs stay in CSS pixels.shoot.jscurrently captures withscale: 'css'— one image pixel per CSS pixel regardless of the emulated device. For scans that emulate high-DPR devices (iPhone DPR 3, common Android profiles at fractional DPRs like 2.625), the page image is a downsample of what the device would actually render, and it looks soft when displayed on high-DPI screens.Proposal
When
report.imageScale > 1:deviceScaleFactor: report.imageScale, andpage.screenshot({scale: 'device'})instead of'css'.The image then has
imageScale ×the pixels of the CSS layout, whilegetBoundingClientRect(and therefore every catalogboxID) remains CSS-pixel by definition — consumers map coordinates onto the image by multiplying byimageScale. Omitted or 1 keeps today's behavior byte-identical.Two implementation notes from testing this in production:
deviceScaleFactorcleanly overrides the--force-device-scale-factor=1launch arg used for chromium head emulation, and rect values are unaffected — verified empirically.A natural policy for callers (ours): set
imageScaleto the scan device's ownwindowOptions.deviceScaleFactor, so the page image is what the emulated device natively renders and the catalog page's DPR matches the test pages' (samesrcset/image-setresource selection).Scope: only
getCatalog's launch andshoot()call sites change; test acts and their launches are untouched. We're running this as a patch in production; happy to submit a PR.