ionic-team / ionic-team/capacitor-camera
Gallery image decoding lacks BitmapFactory.Options/inSampleSize downsampling (potential OOM on large images)
- Dominant language
- TypeScript
- Stars
- 4
- Forks
- 1
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 2
Description
### Description
`IonCameraFlow.handleGalleryMediaResults()` (android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt)
decodes gallery-selected images at full resolution before reading EXIF metadata:
```kotlin
val bitmap = BitmapFactory.decodeFile(mediaResult.uri)
```
This call passes no `BitmapFactory.Options`, so there's no `inSampleSize` downsampling — a full-resolution `Bitmap` is allocated in memory purely to extract EXIF data, even though only image dimensions/orientation are needed. On devices with limited memory, or with very large source images (e.g. modern phone cameras producing 12+ MP photos, or large PNG screenshots), this can cause high memory pressure or an `OutOfMemoryError`.
A related helper, `IONCAMRMediaHelper.getImageResolution()` (from `io.ionic.libs.ioncameralib`), appears to follow the same pattern based on its usage — reading image dimensions without the standard two-pass `inJustDecodeBounds` → calculate `inSampleSize` → decode approach recommended by the [Android docs on loading large bitmaps efficiently](https://developer.android.com/topic/performance/graphics/load-bitmap).
### Observed mitigation, but not a fix
`CameraPlugin.java` does catch `OutOfMemoryError` around related bitmap processing, so the plugin doesn't crash uncontrolled today — but that's a reactive safety net, not a fix for the underlying unbounded allocation.
### Suggested fix
Since only image dimensions/orientation are needed here (not the full pixel buffer), the simplest fix may be to skip `decodeFile` entirely for this purpose — Android's `ExifInterface` class can read orientation directly from the file without decoding a bitmap at all. If a bitmap decode is genuinely needed elsewhere in the flow, use the standard two-pass approach: decode with `inJustDecodeBounds = true` first to read dimensions cheaply, then calculate `inSampleSize` before a real decode.
### Environment
- `@capacitor/camera` version: `8.2.3` (latest stable at time of filing)
- Checked `CHANGELOG.md` — no entries reference bitmap decoding, downsampling, `inSampleSize`, or OOM handling in this area.
Contributor guide
Research direction
Start in android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt at IonCameraFlow.handleGalleryMediaResults() and inspect how the decoded bitmap is used for EXIF metadata. Check the related IONCAMRMediaHelper.getImageResolution() usage and CameraPlugin.java's bitmap error handling. Done means gallery images no longer require an unbounded full-resolution allocation for dimensions or orientation, with focused Android tests or verification covering large images.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, java, kotlin
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100