fix(images): use dual DPI baselines for correct pixelRatio on all platforms#8163
Merged
mimecuvalo merged 4 commits intomainfrom Mar 6, 2026
Merged
fix(images): use dual DPI baselines for correct pixelRatio on all platforms#8163mimecuvalo merged 4 commits intomainfrom
mimecuvalo merged 4 commits intomainfrom
Conversation
…tion High-DPI PNGs (e.g. 2x screenshots) have their logical size stored in asset.props.w/h but their true pixel dimensions are larger. Without knowing the pixelRatio, the CDN image resize endpoints cap the requested width at the logical size, returning a downscaled image that looks blurry on retina displays. This adds an optional pixelRatio property to TLImageAsset, populated from the PNG pHYs chunk via MediaHelpers.getImageSize(), and uses it in both multiplayerAssetStore and createDemoAssetStore to request the correct pixel-level width from image transform endpoints. Made-with: Cursor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
5 Skipped Deployments
|
Made-with: Cursor
…latforms The previous 72 DPI baseline was only correct for macOS. Standard 96 DPI PNGs (common on Windows and from tools like Photoshop/GIMP) got a pixelRatio of ~1.333 instead of 1, making them appear ~25% smaller. Now tries both baselines (96 for Windows/web, 72 for macOS) and picks whichever yields a clean integer ratio > 1. This correctly handles: - 96 DPI (Windows 1x) → ratio 1 - 72 DPI (macOS 1x) → ratio 1 - 144 DPI (macOS 2x Retina) → ratio 2 - 192 DPI (Windows 2x HiDPI) → ratio 2 Made-with: Cursor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
steveruizok
reviewed
Mar 6, 2026
1 task
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 18, 2026
In order to publish the v4.5.0 release notes and record the v4.4.1 patch, this PR archives release notes and resets `next.mdx` for the next cycle. **v4.5.0.mdx** (new file): - Archived from `next.mdx` with full frontmatter, keywords, and GitHub release link - Featured sections: click-through on transparent image pixels (#7942), breaking `EmbedShapeUtil.configure()` change (#8034) - API changes: `Editor.getResizeScaleFactor()` (#8042), `TLImageAsset.pixelRatio` (#8163), `sanitizeSvg` (#7896), `experimental__onDropOnCanvas` (#7911), enum-to-const refactoring (#8084) - 6 improvements and 20 bug fixes from production **v4.4.0.mdx:** - Add v4.4.1 patch release section with tooltip positioning fix (#8171) - Add v4.4.1 to keywords **next.mdx:** - Reset with `last_version: v4.5.0` and empty content ### Change type - [x] `other` ### Code changes | Section | LOC change | | ------------- | ------------- | | Documentation | +128 / -107 |
huppy-bot bot
pushed a commit
that referenced
this pull request
Mar 18, 2026
In order to publish the v4.5.0 release notes and record the v4.4.1 patch, this PR archives release notes and resets `next.mdx` for the next cycle. **v4.5.0.mdx** (new file): - Archived from `next.mdx` with full frontmatter, keywords, and GitHub release link - Featured sections: click-through on transparent image pixels (#7942), breaking `EmbedShapeUtil.configure()` change (#8034) - API changes: `Editor.getResizeScaleFactor()` (#8042), `TLImageAsset.pixelRatio` (#8163), `sanitizeSvg` (#7896), `experimental__onDropOnCanvas` (#7911), enum-to-const refactoring (#8084) - 6 improvements and 20 bug fixes from production **v4.4.0.mdx:** - Add v4.4.1 patch release section with tooltip positioning fix (#8171) - Add v4.4.1 to keywords **next.mdx:** - Reset with `last_version: v4.5.0` and empty content ### Change type - [x] `other` ### Code changes | Section | LOC change | | ------------- | ------------- | | Documentation | +128 / -107 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
High-DPI PNGs (e.g. Retina screenshots) store their logical size in
asset.props.w/h, but their actual pixel dimensions are larger. Without knowing the pixel ratio, the CDN image resize endpoints cap the requested width at the logical size, returning a downscaled image that looks blurry on retina displays.This PR adds an optional
pixelRatioproperty toTLImageAsset, populated from the PNG pHYs chunk viaMediaHelpers.getImageSize(), and uses it in bothmultiplayerAssetStoreandcreateDemoAssetStoreto request the correct pixel-level width from image transform endpoints.The pHYs DPI detection now tries both standard baselines — 96 DPI (Windows/web) and 72 DPI (macOS) — and picks whichever yields a clean integer ratio above 1. This correctly handles all common cases:
The previous implementation used 72 DPI as the sole baseline, which was only correct for macOS. Any standard 96 DPI PNG (extremely common from Windows and tools like Photoshop/GIMP) got a pixelRatio of ~1.333, causing those images to appear ~25% smaller than intended.
before+after (looking at her blue hair can show you the crispness of the lines)


Change type
improvementAPI changes
pixelRatioproperty toTLImageAssetpixelRatio: numbertoMediaHelpers.getImageSize()return typeAddPixelRatio(version 6) for image assetsTest plan
pixelRatio: 2and display at half its pixel dimensionspixelRatioset (treated as 1) and display at full pixel sizepixelRatio: 2Release notes
Note
Medium Risk
Introduces a new optional
TLImageAsset.props.pixelRatioand uses it to change how resized image URLs are computed, which can affect image rendering quality and bandwidth/costs across clients. Also updates schema validation/migrations andMediaHelpers.getImageSize’s return type, so downstream consumers may need to handle the new field.Overview
Fixes blurry/incorrectly scaled high-DPI PNG rendering by recording the source
pixelRatioon image assets and using it when generating resize URLs.MediaHelpers.getImageSizenow returns{ w, h, pixelRatio }and detects pixel ratio from PNGpHYsusing dual 96/72 DPI baselines.TLImageAssetgains optionalpixelRatiowith validator + migration (AddPixelRatio), and bothmultiplayerAssetStoreand the sync demo asset store scale requested transform width byw * pixelRatioto fetch true-resolution images.Written by Cursor Bugbot for commit 864fe31. This will update automatically on new commits. Configure here.