Skip to content

fix(android): don't upscale sources without a size past maxSize - #445

Open
daveallie wants to merge 1 commit into
JimmyDaddy:masterfrom
daveallie:fix/android-unknown-size-upscale
Open

daveallie wants to merge 1 commit into
JimmyDaddy:masterfrom
daveallie:fix/android-unknown-size-upscale

Conversation

@daveallie

@daveallie daveallie commented Oct 6, 2026 •

Copy link
Copy Markdown

Summary

Fixes #444.

On Android, a Coil-loaded source with no width/height (file://, content://, http(s)://) was scaled up to fill maxSize x maxSize. With the default maxSize of 2048, a 1600x1200 photo came out at 2048x1536. iOS, ImageMarkerCore.fitWithinMax and the maxSize docs all treat it as an upper bound only.

With no source size, the loader requests .size(maxSize, maxSize).scale(Scale.FIT). The request has no target view, so Coil 2 resolves it to Precision.EXACT, and BitmapFactoryDecoder only skips upscaling when an inexact size is allowed. This PR sets Precision.INEXACT for that case only:

  • Smaller sources keep their own size, as in 1.x, which used Size.ORIGINAL here.
  • Larger sources are still scaled down to fit within maxSize. With an inexact size, Coil still scales down and only skips scaling up.
  • Sources with an explicit width/height keep their existing exact sizing, so resource/asset sizing doesn't change.

Validation

  • Added MarkerImageLoaderTest.doesNotUpscaleCoilSourceWithoutExplicitSize. It loads the 3x2 test content-provider image with the default maxSize.
    • Before the fix: AssertionError: expected:<3> but was:<2048>
    • After the fix: passes
  • MarkerImageLoaderTest + ImageMarkerRendererTest (32 tests) and ImageMarkerJsE2ETest (4 tests, with Metro) all pass on a Pixel 9 API 35 emulator.
    • This includes repeatedlyDownsamplesLargeInputsWithinTheMemoryBound and base64DecodeFitsSourceWithinMaxSizeWithoutCropping, which cover the scale-down path.
  • npm run typecheck
  • npm run lint
  • npx jest (158 tests)

When a Coil-loaded source has no width/height, the loader requests
maxSize x maxSize with Scale.FIT. With no target view Coil resolves that
to exact precision and scales smaller images up to fill it, so a 1600px
photo came back at 2048px with the default maxSize. Request inexact
precision in that case so maxSize is only an upper bound, matching iOS,
fitWithinMax and the documented behavior.

Fixes JimmyDaddy#444

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@daveallie
daveallie requested a review from JimmyDaddy as a code owner October 6, 2026 05:55

This branch has not been deployed

No deployments
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.

[Bug]: Android upscales images without a source size to fill maxSize

1 participant