diff --git a/README.md b/README.md
index dfa7e2f..9eedcd3 100755
--- a/README.md
+++ b/README.md
@@ -49,6 +49,7 @@ ImageEditor.cropImage(uri, cropData).then(url => {
| `size` | Yes | Size (dimensions) of the cropped image |
| `displaySize` | No | Size to which you want to scale the cropped image |
| `resizeMode` | No | Resizing mode to use when scaling the image (iOS only, android resize mode is always 'cover') **Default value**: 'contain' |
+| `quality` | No | The quality of the resulting image, expressed as a value from `0.0` to `1.0`.
The value `0.0` represents the maximum compression (or lowest quality) while the value `1.0` represents the least compression (or best quality).
iOS supports only `JPEG` format, while Android supports both `JPEG`, `WEBP` and `PNG` formats.
**Default value**: (iOS: `1`), (Android: `0.9`) |
```ts
cropData: ImageCropData = {
@@ -56,6 +57,7 @@ cropData: ImageCropData = {
size: {width: number, height: number},
displaySize: {width: number, height: number},
resizeMode: 'contain' | 'cover' | 'stretch',
+ quality: number // 0...1
};
```
diff --git a/android/src/main/java/com/reactnativecommunity/imageeditor/ImageEditorModuleImpl.kt b/android/src/main/java/com/reactnativecommunity/imageeditor/ImageEditorModuleImpl.kt
index f49b5ac..0ba83ac 100644
--- a/android/src/main/java/com/reactnativecommunity/imageeditor/ImageEditorModuleImpl.kt
+++ b/android/src/main/java/com/reactnativecommunity/imageeditor/ImageEditorModuleImpl.kt
@@ -90,6 +90,8 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
fun cropImage(uri: String?, options: ReadableMap, promise: Promise) {
val offset = if (options.hasKey("offset")) options.getMap("offset") else null
val size = if (options.hasKey("size")) options.getMap("size") else null
+ val quality =
+ if (options.hasKey("quality")) (options.getDouble("quality") * 100).toInt() else 90
if (
offset == null ||
size == null ||
@@ -103,6 +105,12 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
if (uri.isNullOrEmpty()) {
throw JSApplicationIllegalArgumentException("Please specify a URI")
}
+ if (quality > 100 || quality < 0) {
+ promise.reject(
+ JSApplicationIllegalArgumentException("quality must be a number between 0 and 1")
+ )
+ return
+ }
val x = offset.getDouble("x").toInt()
val y = offset.getDouble("y").toInt()
val width = size.getDouble("width").toInt()
@@ -144,7 +152,7 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
}
val tempFile = createTempFile(reactContext, mimeType)
- writeCompressedBitmapToFile(cropped, mimeType, tempFile)
+ writeCompressedBitmapToFile(cropped, mimeType, tempFile, quality)
if (mimeType == "image/jpeg") {
copyExif(reactContext, Uri.parse(uri), tempFile)
}
@@ -275,9 +283,6 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
)
private const val TEMP_FILE_PREFIX = "ReactNative_cropped_image_"
- /** Compress quality of the output file. */
- private const val COMPRESS_QUALITY = 90
-
@SuppressLint("InlinedApi")
private val EXIF_ATTRIBUTES =
arrayOf(
@@ -374,9 +379,14 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
}
@Throws(IOException::class)
- private fun writeCompressedBitmapToFile(cropped: Bitmap, mimeType: String, tempFile: File) {
+ private fun writeCompressedBitmapToFile(
+ cropped: Bitmap,
+ mimeType: String,
+ tempFile: File,
+ compressQuality: Int
+ ) {
FileOutputStream(tempFile).use {
- cropped.compress(getCompressFormatForType(mimeType), COMPRESS_QUALITY, it)
+ cropped.compress(getCompressFormatForType(mimeType), compressQuality, it)
}
}
diff --git a/ios/RNCImageEditor.mm b/ios/RNCImageEditor.mm
index 749a354..bc66552 100644
--- a/ios/RNCImageEditor.mm
+++ b/ios/RNCImageEditor.mm
@@ -56,6 +56,10 @@ - (void) cropImage:(NSString *)uri
}
NSString *displaySize = data.resizeMode();
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:[NSURL URLWithString: uri]];
+ CGFloat compressionQuality = 1;
+ if (data.quality().has_value()) {
+ compressionQuality = *data.quality();
+ }
#else
RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
cropData:(NSDictionary *)cropData
@@ -69,6 +73,10 @@ - (void) cropImage:(NSString *)uri
if(displaySize){
targetSize = [RCTConvert CGSize:cropData[@"displaySize"]];
}
+ CGFloat compressionQuality = 1;
+ if(cropData[@"quality"]){
+ compressionQuality = [RCTConvert CGFloat:cropData[@"quality"]];
+ }
#endif
CGRect rect = {offset,size};
NSURL *url = [imageRequest URL];
@@ -80,6 +88,10 @@ - (void) cropImage:(NSString *)uri
reject(@(error.code).stringValue, error.description, error);
return;
}
+ if (compressionQuality > 1 || compressionQuality < 0) {
+ reject(RCTErrorUnspecified, @("quality must be a number between 0 and 1"), nil);
+ return;
+ }
// Crop image
CGRect targetRect = {{-rect.origin.x, -rect.origin.y}, image.size};
@@ -104,7 +116,7 @@ - (void) cropImage:(NSString *)uri
}
else{
- imageData = UIImageJPEGRepresentation(croppedImage, 1);
+ imageData = UIImageJPEGRepresentation(croppedImage, compressionQuality);
path = [RNCFileSystem generatePathInDirectory:[[RNCFileSystem cacheDirectoryPath] stringByAppendingPathComponent:@"ReactNative_cropped_image_"] withExtension:@".jpg"];
}
diff --git a/src/NativeRNCImageEditor.ts b/src/NativeRNCImageEditor.ts
index 5d7b21c..96db64c 100644
--- a/src/NativeRNCImageEditor.ts
+++ b/src/NativeRNCImageEditor.ts
@@ -1,5 +1,5 @@
import type { TurboModule } from 'react-native';
-import type { Double } from 'react-native/Libraries/Types/CodegenTypes';
+import type { Double, Float } from 'react-native/Libraries/Types/CodegenTypes';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
@@ -35,6 +35,11 @@ export interface Spec extends TurboModule {
* `displaySize` param is not specified, this has no effect.
*/
resizeMode?: string;
+
+ /**
+ * (Optional) Compression quality jpg images (number from 0 to 1).
+ */
+ quality?: Float;
}
): Promise;
}