diff --git a/README.md b/README.md index 67ecc70bc..958c0988e 100644 --- a/README.md +++ b/README.md @@ -106,22 +106,23 @@ The `callback` will be called with a response object, refer to [The Response Obj ## Options -| Option | iOS | Android | Web | Description | -| ----------------------- | --- | ------- | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| mediaType | OK | OK | OK | `photo` or `video` or `mixed`(`launchCamera` on Android does not support 'mixed'). Web only supports 'photo' for now. | -| maxWidth | OK | OK | NO | To resize the image. | -| maxHeight | OK | OK | NO | To resize the image. | -| videoQuality | OK | OK | NO | `low`, `medium`, or `high` on iOS, `low` or `high` on Android. | -| durationLimit | OK | OK | NO | Video max duration (in seconds). | -| quality | OK | OK | NO | 0 to 1, photos. | -| cameraType | OK | OK | NO | 'back' or 'front' (May not be supported in few android devices). | -| includeBase64 | OK | OK | OK | If `true`, creates base64 string of the image (Avoid using on large image files due to performance). | -| includeExtra | OK | OK | NO | If `true`, will include extra data which requires library permissions to be requested (i.e. exif data). | -| saveToPhotos | OK | OK | NO | (Boolean) Only for `launchCamera`, saves the image/video file captured to public photo. | -| selectionLimit | OK | OK | OK | Supports providing any integer value. Use `0` to allow any number of files on iOS version >= 14 & Android version >= 13. Default is `1`. | -| presentationStyle | OK | NO | NO | Controls how the picker is presented. `currentContext`, `pageSheet`, `fullScreen`, `formSheet`, `popover`, `overFullScreen`, `overCurrentContext`. Default is `currentContext`. | -| formatAsMp4 | OK | NO | NO | Converts the selected video to MP4 (iOS Only). | -| assetRepresentationMode | OK | NO | NO | A mode that determines which representation to use if an asset contains more than one. Possible values: 'auto', 'current', 'compatible'. Default is 'auto'. | +| Option | iOS | Android | Web | Description | +| ----------------------- | --- | ------- | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| mediaType | OK | OK | OK | `photo` or `video` or `mixed`(`launchCamera` on Android does not support 'mixed'). Web only supports 'photo' for now. | +| maxWidth | OK | OK | NO | To resize the image. | +| maxHeight | OK | OK | NO | To resize the image. | +| videoQuality | OK | OK | NO | `low`, `medium`, or `high` on iOS, `low` or `high` on Android. | +| durationLimit | OK | OK | NO | Video max duration (in seconds). | +| quality | OK | OK | NO | 0 to 1, photos. | +| conversionQuality | NO | OK | NO | For conversion from HEIC to JPEG, 0 to 1. Default is `0.92` | +| cameraType | OK | OK | NO | 'back' or 'front' (May not be supported in few android devices). | +| includeBase64 | OK | OK | OK | If `true`, creates base64 string of the image (Avoid using on large image files due to performance). | +| includeExtra | OK | OK | NO | If `true`, will include extra data which requires library permissions to be requested (i.e. exif data). | +| saveToPhotos | OK | OK | NO | (Boolean) Only for `launchCamera`, saves the image/video file captured to public photo. | +| selectionLimit | OK | OK | OK | Supports providing any integer value. Use `0` to allow any number of files on iOS version >= 14 & Android version >= 13. Default is `1`. | +| presentationStyle | OK | NO | NO | Controls how the picker is presented. `currentContext`, `pageSheet`, `fullScreen`, `formSheet`, `popover`, `overFullScreen`, `overCurrentContext`. Default is `currentContext`. | +| formatAsMp4 | OK | NO | NO | Converts the selected video to MP4 (iOS Only). | +| assetRepresentationMode | OK | OK | NO | A mode that determines which representation to use if an asset contains more than one on iOS or disables HEIC to JPEG conversion on Android if set to 'current'. Possible values: 'auto', 'current', 'compatible'. Default is 'auto'. | ## The Response Object diff --git a/android/src/main/java/com/imagepicker/Options.java b/android/src/main/java/com/imagepicker/Options.java index 55c441af6..0fcca5649 100644 --- a/android/src/main/java/com/imagepicker/Options.java +++ b/android/src/main/java/com/imagepicker/Options.java @@ -10,6 +10,8 @@ public class Options { Boolean includeExtra; int videoQuality = 1; int quality; + int conversionQuality = 92; + Boolean convertToJpeg = true; int maxWidth; int maxHeight; Boolean saveToPhotos; @@ -29,6 +31,15 @@ public class Options { videoQuality = 0; } + if (options.hasKey("conversionQuality")) { + conversionQuality = (int) (options.getDouble("conversionQuality") * 100); + } + + String assetRepresentationMode = options.getString("assetRepresentationMode"); + if (!TextUtils.isEmpty(assetRepresentationMode) && assetRepresentationMode.toLowerCase().equals("current")) { + convertToJpeg = false; + } + if (options.getString("cameraType").equals("front")) { useFrontCamera = true; } diff --git a/android/src/main/java/com/imagepicker/Utils.java b/android/src/main/java/com/imagepicker/Utils.java index 1e9078d3f..af4faa4ae 100644 --- a/android/src/main/java/com/imagepicker/Utils.java +++ b/android/src/main/java/com/imagepicker/Utils.java @@ -202,33 +202,46 @@ private static boolean needToSwapDimension(String orientation){ || orientation.equals(String.valueOf(ExifInterface.ORIENTATION_ROTATE_270)); } - // Resize image + private static boolean shouldConvertToJpeg(String mimeType, Options options) { + return options.convertToJpeg && mimeType != null && mimeType.equals("image/heic"); + } + + // Resize image and/or convert it from HEIC to JPEG // When decoding a jpg to bitmap all exif meta data will be lost, so make sure to copy orientation exif to new file else image might have wrong orientations - public static Uri resizeImage(Uri uri, Context context, Options options) { + public static Uri resizeOrConvertImage(Uri uri, Context context, Options options) { try { int[] origDimens = getImageDimensions(uri, context); + String mimeType = getMimeType(uri, context); + + int targetQuality; if (!shouldResizeImage(origDimens[0], origDimens[1], options)) { - return uri; + if (shouldConvertToJpeg(mimeType, options)) { + mimeType = "image/jpeg"; + targetQuality = options.conversionQuality; + } else { + return uri; + } + } else { + targetQuality = options.quality; } int[] newDimens = getImageDimensBasedOnConstraints(origDimens[0], origDimens[1], options); try (InputStream imageStream = context.getContentResolver().openInputStream(uri)) { - String mimeType = getMimeType(uri, context); Bitmap b = BitmapFactory.decodeStream(imageStream); String originalOrientation = getOrientation(uri, context); if (needToSwapDimension(originalOrientation)) { b = Bitmap.createScaledBitmap(b, newDimens[1], newDimens[0], true); - }else { + } else { b = Bitmap.createScaledBitmap(b, newDimens[0], newDimens[1], true); } File file = createFile(context, getFileTypeFromMime(mimeType)); try (OutputStream os = context.getContentResolver().openOutputStream(Uri.fromFile(file))) { - b.compress(getBitmapCompressFormat(mimeType), options.quality, os); + b.compress(getBitmapCompressFormat(mimeType), targetQuality, os); } setOrientation(file, originalOrientation, context); @@ -558,7 +571,7 @@ static ReadableMap getResponseMap(List fileUris, Options options, Context c // Call getAppSpecificStorageUri in the if block to avoid copying unsupported files if (isImageType(uri, context)) { - appSpecificUrl = resizeImage(appSpecificUrl, context, options); + appSpecificUrl = resizeOrConvertImage(appSpecificUrl, context, options); assets.pushMap(getImageResponseMap(uri, appSpecificUrl, options, context)); } else if (isVideoType(uri, context)) { if (uri.getScheme().contains("content")) { diff --git a/package.json b/package.json index c5ca97d68..1fb2ebd51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-image-picker", - "version": "7.2.3", + "version": "8.0.0", "description": "A React Native module that allows you to use native UI to select media from the device library or directly from the camera", "react-native": "src/index.ts", "main": "src/index.ts",