Skip to content

[image_picker_android] ImageResizer never downsamples: calculateSampleSize reads an Options object that was never decoded #193036

Closed
flutter/packages
#13038

Description

@FatJohn

Steps to reproduce

  1. Use image_picker on Android and pick a large photo (e.g. a 12 MP, 4000x3000 camera image) with a size limit, e.g. ImagePicker().pickImage(source: ImageSource.gallery, maxWidth: 1280, maxHeight: 1280).
  2. Look at how ImageResizer.resizeImageIfNeeded decodes the image (package image_picker_android, file android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java; checked against the latest release, 0.8.13+23).

Expected results

calculateSampleSize picks a power-of-two inSampleSize from the original image size, so the 4000x3000 photo is decoded at 2000x1500 (about 12 MB as ARGB_8888) before createScaledBitmap scales it to 1280x960. This is what flutter/packages#3423 ("Improved Bitmap resize on Android", for #118383) set out to do.

Actual results

inSampleSize is always 1, so the photo is always decoded at full resolution (4000x3000, about 48 MB) before being scaled.

In resizeImageIfNeeded, a fresh BitmapFactory.Options is created and passed straight to calculateSampleSize:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize =
    calculateSampleSize(options, (int) targetSize.getWidth(), (int) targetSize.getHeight());
Bitmap bmp = decodeFile(imagePath, options);

calculateSampleSize reads options.outWidth / options.outHeight, but this options object has never been used for a decode, so those fields still hold their defaults. The condition height > targetHeight || width > targetWidth is therefore never true and the method returns 1. The original dimensions were already read by readFileDimensions(), but into a different Options instance, and only the resulting SizeFCompat is kept.

A side effect is that passing maxWidth / maxHeight makes memory use worse than not passing them: without them the plugin returns the original file untouched, with them it always does a full-resolution decode plus a re-encode. Google Play Console's Android vitals flags this pattern as "Use bitmap downsampling to improve app performance".

A possible fix is to compute the sample size from originalSize (the SizeFCompat returned by readFileDimensions) instead of from the undecoded options.

Code sample

Code sample
final image = await ImagePicker().pickImage(
  source: ImageSource.gallery,
  maxWidth: 1280,
  maxHeight: 1280,
);

Screenshots or Video

N/A

Logs

N/A. The behavior follows directly from the code above; we confirmed it by reproducing calculateTargetSize + calculateSampleSize for 4000x3000, 4032x3024, 4080x3072 and 8160x6120 sources, all of which end up with inSampleSize = 1.

Flutter Doctor output

Doctor output
Flutter 3.47.4 (stable), macOS, Android emulator API 37.
image_picker_android 0.8.13+19 in the app; code inspected in 0.8.13+23 (latest).

Activity

  1. added
    platform-androidAndroid applications specifically
    packageflutter/packages repository. See also p: labels.
    team-androidOwned by Android platform team
    on Sep 21, 2026
  2. mbcorona commented on Sep 21, 2026

    @mbcorona
    Member

    Hi @FatJohn , thanks for the report. Routing to the Android team to check on computing the sample size from originalSize.

  3. jesswrd commented on Sep 22, 2026

    @jesswrd
    Contributor

    @mbcorona Can you check if this is a regression? It looks like the reporter used 3.47.4 (stable), Android emulator API 37, image_picker_android 0.8.13+19.

  4. added
    P2Important issues not at the top of the work list
    triaged-androidTriaged by Android platform team
    on Sep 22, 2026
  5. anilcancakir commented on Sep 27, 2026

    @anilcancakir

    I've sent a fix in flutter/packages#13038.

    calculateSampleSize now uses the dimensions readFileDimensions already read, so a resize with maxWidth or maxHeight subsamples while decoding; the output size is unchanged. To answer the regression question: it is not one, inSampleSize has been 1 since it was introduced in flutter/packages#3423.

  6. github-actions commented on Oct 16, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  7. locked as resolved and limited conversation to collaborators on Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listp: image_pickerThe Image Picker plugin.packageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyteam-androidOwned by Android platform teamtriaged-androidTriaged by Android platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions