diff --git a/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt b/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt index c8e46cf..94c53da 100644 --- a/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt +++ b/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt @@ -143,6 +143,30 @@ class IonCameraFlow( callEditURIPhoto(call) } + private fun decodeSampledBitmap(path: String, maxSize: Int = 2048): android.graphics.Bitmap? { + val options = BitmapFactory.Options().apply { + inJustDecodeBounds = true + } + + BitmapFactory.decodeFile(path, options) + + var sampleSize = 1 + while ( + options.outWidth / sampleSize > maxSize || + options.outHeight / sampleSize > maxSize + ) { + sampleSize *= 2 + } + + return BitmapFactory.decodeFile( + path, + BitmapFactory.Options().apply { + inSampleSize = sampleSize + } + ) + } + + // ---------------------------------------------------- // Launchers // ---------------------------------------------------- @@ -719,7 +743,7 @@ class IonCameraFlow( private fun handleMediaResult(mediaResult: IONCAMRMediaResult) { val file = File(mediaResult.uri) val uri = Uri.fromFile(file) - val bitmap = BitmapFactory.decodeFile(mediaResult.uri) + val bitmap = decodeSampledBitmap(mediaResult.uri) if (bitmap == null) { sendError(IONCAMRError.PROCESS_IMAGE_ERROR) return @@ -799,7 +823,7 @@ class IonCameraFlow( metadata.put("creationDate", it.creationDate) if (mediaResult.type == IONCAMRMediaType.PICTURE.type) { - val bitmap = BitmapFactory.decodeFile(mediaResult.uri) + val bitmap = decodeSampledBitmap(mediaResult.uri) if (bitmap == null) { sendError(IONCAMRError.PROCESS_IMAGE_ERROR) return diff --git a/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java b/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java index 7922106..b008cdf 100644 --- a/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java +++ b/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java @@ -371,6 +371,64 @@ private void openPhotos(final PluginCall call, boolean multiple) { } } + +private static final int MAX_BITMAP_SIZE = 2048; + +private int calculateInSampleSize( + BitmapFactory.Options options, + int maxSize +) { + int width = options.outWidth; + int height = options.outHeight; + int inSampleSize = 1; + + while (width / inSampleSize > maxSize || + height / inSampleSize > maxSize) { + inSampleSize *= 2; + } + + return inSampleSize; +} + +private Bitmap decodeSampledBitmapFromFile(String path) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + + BitmapFactory.decodeFile(path, options); + + options.inSampleSize = + calculateInSampleSize(options, MAX_BITMAP_SIZE); + options.inJustDecodeBounds = false; + + return BitmapFactory.decodeFile(path, options); +} + + private Bitmap decodeSampledBitmapFromUri(Uri uri) + throws FileNotFoundException { + + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + + try (InputStream stream = + context.getContentResolver().openInputStream(uri)) { + BitmapFactory.decodeStream(stream, null, options); + } catch (IOException e) { + throw new RuntimeException("Unable to read image", e); + } + + options.inSampleSize = + calculateInSampleSize(options, MAX_BITMAP_SIZE); + options.inJustDecodeBounds = false; + + try (InputStream stream = + context.getContentResolver().openInputStream(uri)) { + return BitmapFactory.decodeStream(stream, null, options); + } catch (IOException e) { + throw new RuntimeException("Unable to read image", e); + } + } + + public void processCameraImage(PluginCall call, ActivityResult result) { settings = getSettings(call); if (imageFileSavePath == null) { @@ -379,9 +437,8 @@ public void processCameraImage(PluginCall call, ActivityResult result) { } // Load the image as a Bitmap File f = new File(imageFileSavePath); - BitmapFactory.Options bmOptions = new BitmapFactory.Options(); Uri contentUri = Uri.fromFile(f); - Bitmap bitmap = BitmapFactory.decodeFile(imageFileSavePath, bmOptions); + Bitmap bitmap = decodeSampledBitmapFromFile(imageFileSavePath); if (bitmap == null) { call.reject(USER_CANCELLED); @@ -415,9 +472,7 @@ private void processPickedImage(Uri imageUri, PluginCall call) { InputStream imageStream = null; try { - imageStream = context.getContentResolver().openInputStream(imageUri); - Bitmap bitmap = BitmapFactory.decodeStream(imageStream); - + Bitmap bitmap = decodeSampledBitmapFromUri(imageUri); if (bitmap == null) { call.reject("Unable to process bitmap"); return; @@ -443,9 +498,8 @@ private JSObject processPickedImages(Uri imageUri) { InputStream imageStream = null; JSObject ret = new JSObject(); try { - imageStream = context.getContentResolver().openInputStream(imageUri); - Bitmap bitmap = BitmapFactory.decodeStream(imageStream); + Bitmap bitmap = decodeSampledBitmapFromUri(imageUri); if (bitmap == null) { ret.put("error", "Unable to process bitmap"); return ret;