[] [Android] maxWidth/maxHeight silently fail to resize large images (full-res decode returns original)

Author: yildirayyorulmazCreated Jul 23, 2026Updated Aug 30, 2026
Labels:bug: Bug

Description

On Android, the maxWidth / maxHeight options do not reliably resize picked images. The same options work correctly on iOS. For large source photos (e.g. 12 MP camera images), the returned asset keeps its original full resolution instead of being downscaled to fit within maxWidth × maxHeight.

Root cause is in Utils.resizeOrConvertImage() (android/src/main/java/com/imagepicker/Utils.java). The resize decodes the entire full-resolution bitmap into memory with no downsampling, then scales it down afterward:

java
try (InputStream imageStream = context.getContentResolver().openInputStream(uri)) {
    Bitmap b = BitmapFactory.decodeStream(imageStream);          // full-res, no inSampleSize
    ...
    b = Bitmap.createScaledBitmap(b, newDimens[0], newDimens[1], true);
    ...
} catch (Exception e) {
    e.printStackTrace();
    return uri; // cannot resize the image, return the ORIGINAL uri
}

For large images, BitmapFactory.decodeStream returns null (Android's documented behavior when it cannot allocate the full bitmap). Bitmap.createScaledBitmap(null, …) then throws a NullPointerException, which is swallowed by the broad catch (Exception e) and the method silently returns the original, un-resized URI. The failure is invisible to the JS caller — no error, just an unresized image.

Notably, the library already uses the memory-safe pattern (BitmapFactory.Options.inJustDecodeBounds = true) in getImageDimensions(), but does not apply inSampleSize in the actual resize decode. iOS uses ImageIO/Core Image thumbnailing, which downsamples during decode, so it is unaffected.

This is not fixed in any released version. The current main branch contains the identical naive implementation.

How to repeat issue and example

  1. Use a physical Android device with a high-resolution camera (or a large gallery image, e.g. 4000×3000).
  2. Call launchImageLibrary (or launchCamera) with resize constraints:
    javascript
    launchImageLibrary({
      mediaType: 'photo',
      maxWidth: 1024,
      maxHeight: 1024,
      quality: 1,
    });
  3. Inspect the returned asset's width / height (and file size).
  4. Expected: the image is downscaled so the longest side is ≤ 1024.
  5. Actual (Android): the returned asset keeps its original dimensions (e.g. 4000×3000). The same code on iOS returns a correctly resized ~1024 px image.

Reproducible reliably with large source images; smaller images (already within the max bounds) are unaffected because no resize is attempted.

Solution

Decode the bitmap with downsampling instead of loading it at full resolution. Compute an appropriate inSampleSize from the source dimensions and the target constraints, then decode:

java
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri), null, bounds);

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = calculateInSampleSize(bounds, targetWidth, targetHeight);
Bitmap b = BitmapFactory.decodeStream(
    context.getContentResolver().openInputStream(uri), null, opts);

Additionally:

  • Narrow the catch (Exception e) so genuine decode failures are surfaced rather than silently returning the original image, and/or return an explicit error to JS.
  • Consider guarding against OutOfMemoryError (subtype of Error, currently not caught).

Additional Information

  • Image Picker version: 8.2.1 (also confirmed present in current main)
  • React Native version: 0.83.1 (New Architecture / TurboModules enabled)
  • Platform: Android (iOS works correctly)
  • Development Operating System: macOS
  • Dev tools: Android Gradle Plugin with compileSdkVersion / targetSdkVersion 36, minSdkVersion 29, NDK 27.1.12297006, Kotlin 2.1.20. Reproduced on a physical Android device picking large gallery/camera images.

Note: This issue report was authored with the assistance of Claude Opus 4.8.

Source: react-native-image-picker/react-native-image-picker