From 191991d20f205b29f326c11eac73285621bb29e9 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Wed, 24 Jul 2019 17:55:38 +0530 Subject: [PATCH 01/14] New feature : pick images with image quality --- .../plugins/imagepicker/ImagePickerCache.java | 1 + .../imagepicker/ImagePickerDelegate.java | 9 +++-- .../plugins/imagepicker/ImageResizer.java | 20 +++++++---- packages/image_picker/example/lib/main.dart | 3 +- .../ios/Classes/FLTImagePickerMetaDataUtil.m | 18 +++++----- .../Classes/FLTImagePickerPhotoAssetUtil.h | 5 +-- .../Classes/FLTImagePickerPhotoAssetUtil.m | 15 +++++---- .../ios/Classes/ImagePickerPlugin.m | 22 +++++++++---- packages/image_picker/lib/image_picker.dart | 23 ++++++++++--- .../image_picker/test/image_picker_test.dart | 33 +++++++++++++++++++ 10 files changed, 113 insertions(+), 36 deletions(-) diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java index 0f4e97681a1a..7bc1537de5da 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java @@ -18,6 +18,7 @@ class ImagePickerCache { static final String MAP_KEY_PATH = "path"; static final String MAP_KEY_MAX_WIDTH = "maxWidth"; static final String MAP_KEY_MAX_HEIGHT = "maxHeight"; + static final String MAP_KEY_IMAGE_QUALITY = "imageQuality"; private static final String MAP_KEY_TYPE = "type"; private static final String MAP_KEY_ERROR_CODE = "errorCode"; private static final String MAP_KEY_ERROR_MESSAGE = "errorMessage"; diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index 2f2522f53c5c..448bfda98c72 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -210,7 +210,9 @@ void retrieveLostImage(MethodChannel.Result result) { if (path != null) { Double maxWidth = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_WIDTH); Double maxHeight = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_HEIGHT); - String newPath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight); + int imageQuality = (int) resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); + + String newPath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality); resultMap.put(ImagePickerCache.MAP_KEY_PATH, newPath); } if (resultMap.isEmpty()) { @@ -509,7 +511,10 @@ private void handleImageResult(String path, boolean shouldDeleteOriginalIfScaled if (methodCall != null) { Double maxWidth = methodCall.argument("maxWidth"); Double maxHeight = methodCall.argument("maxHeight"); - String finalImagePath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight); + int imageQuality = methodCall.argument("imageQuality"); + + String finalImagePath = + imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality); finishWithSuccess(finalImagePath); diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java index f9bd3adb2e36..1bd1c9e92fd7 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java @@ -26,15 +26,17 @@ class ImageResizer { * *

If no resizing is needed, returns the path for the original image. */ - String resizeImageIfNeeded(String imagePath, Double maxWidth, Double maxHeight) { - boolean shouldScale = maxWidth != null || maxHeight != null; + String resizeImageIfNeeded( + String imagePath, Double maxWidth, Double maxHeight, int imageQuality) { + boolean shouldScale = + maxWidth != null || maxHeight != null || (imageQuality > -1 && imageQuality < 101); if (!shouldScale) { return imagePath; } try { - File scaledImage = resizedImage(imagePath, maxWidth, maxHeight); + File scaledImage = resizedImage(imagePath, maxWidth, maxHeight, imageQuality); exifDataCopier.copyExif(imagePath, scaledImage.getPath()); return scaledImage.getPath(); @@ -43,11 +45,16 @@ String resizeImageIfNeeded(String imagePath, Double maxWidth, Double maxHeight) } } - private File resizedImage(String path, Double maxWidth, Double maxHeight) throws IOException { + private File resizedImage(String path, Double maxWidth, Double maxHeight, int imageQuality) + throws IOException { Bitmap bmp = BitmapFactory.decodeFile(path); double originalWidth = bmp.getWidth() * 1.0; double originalHeight = bmp.getHeight() * 1.0; + if (imageQuality < 0 || imageQuality > 100) { + imageQuality = 100; + } + boolean hasMaxWidth = maxWidth != null; boolean hasMaxHeight = maxHeight != null; @@ -87,7 +94,9 @@ private File resizedImage(String path, Double maxWidth, Double maxHeight) throws ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); boolean saveAsPNG = bmp.hasAlpha(); scaledBmp.compress( - saveAsPNG ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, 100, outputStream); + saveAsPNG ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, + imageQuality, + outputStream); String[] pathParts = path.split("/"); String imageName = pathParts[pathParts.length - 1]; @@ -96,7 +105,6 @@ private File resizedImage(String path, Double maxWidth, Double maxHeight) throws FileOutputStream fileOutput = new FileOutputStream(imageFile); fileOutput.write(outputStream.toByteArray()); fileOutput.close(); - return imageFile; } } diff --git a/packages/image_picker/example/lib/main.dart b/packages/image_picker/example/lib/main.dart index 066c12380b40..ed0667004e01 100755 --- a/packages/image_picker/example/lib/main.dart +++ b/packages/image_picker/example/lib/main.dart @@ -59,7 +59,8 @@ class _MyHomePageState extends State { }); } else { try { - _imageFile = await ImagePicker.pickImage(source: source); + _imageFile = + await ImagePicker.pickImage(source: source, imageQuality: 50); } catch (e) { _pickImageError = e; } diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m index 5123dec11ece..120be9ed25dc 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m @@ -63,14 +63,16 @@ + (NSData *)updateMetaData:(NSDictionary *)metaData toImage:(NSData *)imageData + (NSData *)convertImage:(UIImage *)image usingType:(FLTImagePickerMIMEType)type quality:(nullable NSNumber *)quality { - if (quality && type != FLTImagePickerMIMETypeJPEG) { - @throw [NSException - exceptionWithName:@"flutter_image_picker_convert_image_exception" - reason:[NSString stringWithFormat:@"quality is not available for type %@", - [FLTImagePickerMetaDataUtil - imageTypeSuffixFromType:type]] - userInfo:nil]; - } + +// Commenting as of now as JPEG conversion is done by default +// if (quality && type != FLTImagePickerMIMETypeJPEG) { +// @throw [NSException +// exceptionWithName:@"flutter_image_picker_convert_image_exception" +// reason:[NSString stringWithFormat:@"quality is not available for type %@", +// [FLTImagePickerMetaDataUtil +// imageTypeSuffixFromType:type]] +// userInfo:nil]; +// } switch (type) { case FLTImagePickerMIMETypeJPEG: { diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h index e2b8357cf06f..ca824b982566 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h @@ -18,10 +18,11 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image maxWidth:(nullable NSNumber *)maxWidth - maxHeight:(nullable NSNumber *)maxHeight; + maxHeight:(nullable NSNumber *)maxHeight + imageQuality:(nullable NSNumber *)imageQuality; // Save image with correct meta data and extention copied from image picker result info. -+ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image; ++ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality; @end diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m index bf22e0069278..fe7c1ba251c2 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m @@ -26,7 +26,8 @@ + (PHAsset *)getAssetFromImagePickerInfo:(NSDictionary *)info { + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image maxWidth:(NSNumber *)maxWidth - maxHeight:(NSNumber *)maxHeight { + maxHeight:(NSNumber *)maxHeight + imageQuality:(NSNumber *)imageQuality{ NSString *suffix = kFLTImagePickerDefaultSuffix; FLTImagePickerMIMEType type = kFLTImagePickerMIMETypeDefault; NSDictionary *metaData = nil; @@ -44,16 +45,17 @@ + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData return [self saveImageWithMetaData:metaData gifInfo:gifInfo suffix:suffix]; } else { - return [self saveImageWithMetaData:metaData image:image suffix:suffix type:type]; + return [self saveImageWithMetaData:metaData image:image suffix:suffix type:type imageQuality:imageQuality]; } } -+ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image { ++ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality { NSDictionary *metaData = info[UIImagePickerControllerMediaMetadata]; return [self saveImageWithMetaData:metaData image:image suffix:kFLTImagePickerDefaultSuffix - type:kFLTImagePickerMIMETypeDefault]; + type:kFLTImagePickerMIMETypeDefault + imageQuality:imageQuality]; } + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData @@ -66,7 +68,8 @@ + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData image:(UIImage *)image suffix:(NSString *)suffix - type:(FLTImagePickerMIMEType)type { + type:(FLTImagePickerMIMEType)type + imageQuality:(NSNumber *)imageQuality{ CGImagePropertyOrientation orientation = (CGImagePropertyOrientation)[metaData[( __bridge NSString *)kCGImagePropertyOrientation] integerValue]; UIImage *newImage = [UIImage @@ -76,7 +79,7 @@ + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData [FLTImagePickerMetaDataUtil getNormalizedUIImageOrientationFromCGImagePropertyOrientation:orientation]]; - NSData *data = [FLTImagePickerMetaDataUtil convertImage:newImage usingType:type quality:nil]; + NSData *data = [FLTImagePickerMetaDataUtil convertImage:newImage usingType:type quality:imageQuality]; if (metaData) { data = [FLTImagePickerMetaDataUtil updateMetaData:metaData toImage:data]; } diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index 18803d2e7fff..0ef86b6a49fd 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -251,6 +251,13 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *maxWidth = [_arguments objectForKey:@"maxWidth"]; NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"]; + NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"]; + + if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { + imageQuality = [NSNumber numberWithInt:1]; + }else{ + imageQuality = @([imageQuality floatValue] / 100); + } if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) { image = [FLTImagePickerImageUtil scaledImage:image maxWidth:maxWidth maxHeight:maxHeight]; @@ -259,7 +266,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; if (!originalAsset) { // Image picked without an original asset (e.g. User took a photo directly) - [self saveImageWithPickerInfo:info image:image]; + [self saveImageWithPickerInfo:info image:image imageQuality:imageQuality]; } else { __weak typeof(self) weakSelf = self; [[PHImageManager defaultManager] @@ -271,7 +278,8 @@ - (void)imagePickerController:(UIImagePickerController *)picker [weakSelf saveImageWithOriginalImageData:imageData image:image maxWidth:maxWidth - maxHeight:maxHeight]; + maxHeight:maxHeight + imageQuality:imageQuality]; }]; } } @@ -289,17 +297,19 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { - (void)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image maxWidth:(NSNumber *)maxWidth - maxHeight:(NSNumber *)maxHeight { + maxHeight:(NSNumber *)maxHeight + imageQuality:(NSNumber *)imageQuality{ NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:originalImageData image:image maxWidth:maxWidth - maxHeight:maxHeight]; + maxHeight:maxHeight + imageQuality:imageQuality]; [self handleSavedPath:savedPath]; } -- (void)saveImageWithPickerInfo:(NSDictionary *)info image:(UIImage *)image { - NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info image:image]; +- (void)saveImageWithPickerInfo:(NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality{ + NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info image:image imageQuality:imageQuality]; [self handleSavedPath:savedPath]; } diff --git a/packages/image_picker/lib/image_picker.dart b/packages/image_picker/lib/image_picker.dart index b224b6331ad8..ed7cfb9fc499 100755 --- a/packages/image_picker/lib/image_picker.dart +++ b/packages/image_picker/lib/image_picker.dart @@ -32,14 +32,17 @@ class ImagePicker { /// If specified, the image will be at most [maxWidth] wide and /// [maxHeight] tall. Otherwise the image will be returned at it's /// original width and height. + /// The [imageQuality] argument resize the image as per the input, ranging from 0-100 compression. + /// 0 meaning compress for small size, 100 meaning compress for max quality. + /// Some formats, like PNG which is loss less, will ignore the quality setting /// /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost /// in this call. You can then call [retrieveLostData] when your app relaunches to retrieve the lost data. - static Future pickImage({ - @required ImageSource source, - double maxWidth, - double maxHeight, - }) async { + static Future pickImage( + {@required ImageSource source, + double maxWidth, + double maxHeight, + int imageQuality}) async { assert(source != null); if (maxWidth != null && maxWidth < 0) { @@ -50,12 +53,22 @@ class ImagePicker { throw ArgumentError.value(maxHeight, 'maxHeight cannot be negative'); } + if (null == imageQuality) { + imageQuality = 100; + } + + if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) { + throw ArgumentError.value( + imageQuality, 'invalid imageQuality, must be between 0 and 100'); + } + final String path = await _channel.invokeMethod( 'pickImage', { 'source': source.index, 'maxWidth': maxWidth, 'maxHeight': maxHeight, + 'imageQuality': imageQuality }, ); diff --git a/packages/image_picker/test/image_picker_test.dart b/packages/image_picker/test/image_picker_test.dart index 40226afb77ce..ea81c32b9142 100644 --- a/packages/image_picker/test/image_picker_test.dart +++ b/packages/image_picker/test/image_picker_test.dart @@ -34,11 +34,13 @@ void main() { 'source': 0, 'maxWidth': null, 'maxHeight': null, + 'imageQuality': 100 }), isMethodCall('pickImage', arguments: { 'source': 1, 'maxWidth': null, 'maxHeight': null, + 'imageQuality': 100 }), ], ); @@ -59,6 +61,15 @@ void main() { maxWidth: 10.0, maxHeight: 20.0, ); + await ImagePicker.pickImage( + source: ImageSource.camera, maxWidth: 10.0, imageQuality: 70); + await ImagePicker.pickImage( + source: ImageSource.camera, maxHeight: 10.0, imageQuality: 70); + await ImagePicker.pickImage( + source: ImageSource.camera, + maxWidth: 10.0, + maxHeight: 20.0, + imageQuality: 70); expect( log, @@ -67,21 +78,43 @@ void main() { 'source': 0, 'maxWidth': null, 'maxHeight': null, + 'imageQuality': 100 + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': 10.0, + 'maxHeight': null, + 'imageQuality': 100 + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': 10.0, + 'imageQuality': 100 + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': 10.0, + 'maxHeight': 20.0, + 'imageQuality': 100 }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, + 'imageQuality': 70 }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, + 'imageQuality': 70 }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, + 'imageQuality': 70 }), ], ); From cf66f1faba7a0eae0d5dda36092d40552be1ff17 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Wed, 24 Jul 2019 18:43:17 +0530 Subject: [PATCH 02/14] Updated test cases --- .../imagepicker/ImagePickerDelegateTest.java | 12 ++++++---- .../ios/Classes/ImagePickerPlugin.m | 24 +++++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index 02bb91b7914f..9d9d920a3d6d 100644 --- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -26,6 +26,7 @@ public class ImagePickerDelegateTest { private static final double WIDTH = 10.0; private static final double HEIGHT = 10.0; + private static final double IMAGE_QUALITY = 70; @Mock Activity mockActivity; @Mock ImageResizer mockImageResizer; @@ -60,13 +61,16 @@ public void setUp() { when(mockFileUtils.getPathFromUri(any(Context.class), any(Uri.class))) .thenReturn("pathFromUri"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, -1)) .thenReturn("originalPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, IMAGE_QUALITY)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null)).thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, 0)).thenReturn("scaledPath"); + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, null)) .thenReturn("scaledPath"); + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, IMAGE_QUALITY)) + .thenReturn("scaledPath"); + mockFileUriResolver = new MockFileUriResolver(); diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index 0ef86b6a49fd..036b4445cb1e 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -253,11 +253,11 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"]; NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"]; - if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { - imageQuality = [NSNumber numberWithInt:1]; - }else{ - imageQuality = @([imageQuality floatValue] / 100); - } + if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { + imageQuality = [NSNumber numberWithInt:1]; + }else{ + imageQuality = @([imageQuality floatValue] / 100); + } if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) { image = [FLTImagePickerImageUtil scaledImage:image maxWidth:maxWidth maxHeight:maxHeight]; @@ -266,7 +266,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; if (!originalAsset) { // Image picked without an original asset (e.g. User took a photo directly) - [self saveImageWithPickerInfo:info image:image imageQuality:imageQuality]; + [self saveImageWithPickerInfo:info image:image imageQuality:imageQuality]; } else { __weak typeof(self) weakSelf = self; [[PHImageManager defaultManager] @@ -298,18 +298,22 @@ - (void)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image maxWidth:(NSNumber *)maxWidth maxHeight:(NSNumber *)maxHeight - imageQuality:(NSNumber *)imageQuality{ + imageQuality:(NSNumber *)imageQuality { NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:originalImageData image:image maxWidth:maxWidth maxHeight:maxHeight - imageQuality:imageQuality]; + imageQuality:imageQuality]; [self handleSavedPath:savedPath]; } -- (void)saveImageWithPickerInfo:(NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality{ - NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info image:image imageQuality:imageQuality]; +- (void)saveImageWithPickerInfo:(NSDictionary *)info + image:(UIImage *)image + imageQuality:(NSNumber *)imageQuality{ + NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info + image:image + imageQuality:imageQuality]; [self handleSavedPath:savedPath]; } From 9d14063ca4f78dd42e2aee1bde599eb004fe7fe2 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Wed, 24 Jul 2019 19:04:21 +0530 Subject: [PATCH 03/14] Code formmated --- .../plugins/imagepicker/ImagePickerDelegateTest.java | 6 +++--- .../image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h | 4 +++- .../image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m | 6 +++--- packages/image_picker/ios/Classes/ImagePickerPlugin.m | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index 9d9d920a3d6d..380241c23fd5 100644 --- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -65,12 +65,12 @@ public void setUp() { .thenReturn("originalPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, IMAGE_QUALITY)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, 0)).thenReturn("scaledPath"); + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, 0)) + .thenReturn("scaledPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, null)) .thenReturn("scaledPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, IMAGE_QUALITY)) - .thenReturn("scaledPath"); - + .thenReturn("scaledPath"); mockFileUriResolver = new MockFileUriResolver(); diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h index ca824b982566..417a6f9a7399 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h @@ -22,7 +22,9 @@ NS_ASSUME_NONNULL_BEGIN imageQuality:(nullable NSNumber *)imageQuality; // Save image with correct meta data and extention copied from image picker result info. -+ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality; ++ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info + image:(UIImage *)image + imageQuality:(NSNumber *)imageQuality; @end diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m index fe7c1ba251c2..172ed1276fb1 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m @@ -27,7 +27,7 @@ + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image maxWidth:(NSNumber *)maxWidth maxHeight:(NSNumber *)maxHeight - imageQuality:(NSNumber *)imageQuality{ + imageQuality:(NSNumber *)imageQuality { NSString *suffix = kFLTImagePickerDefaultSuffix; FLTImagePickerMIMEType type = kFLTImagePickerMIMETypeDefault; NSDictionary *metaData = nil; @@ -46,7 +46,7 @@ + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData return [self saveImageWithMetaData:metaData gifInfo:gifInfo suffix:suffix]; } else { return [self saveImageWithMetaData:metaData image:image suffix:suffix type:type imageQuality:imageQuality]; - } + } } + (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality { @@ -69,7 +69,7 @@ + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData image:(UIImage *)image suffix:(NSString *)suffix type:(FLTImagePickerMIMEType)type - imageQuality:(NSNumber *)imageQuality{ + imageQuality:(NSNumber *)imageQuality { CGImagePropertyOrientation orientation = (CGImagePropertyOrientation)[metaData[( __bridge NSString *)kCGImagePropertyOrientation] integerValue]; UIImage *newImage = [UIImage diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index 036b4445cb1e..301ddc2570a5 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -255,7 +255,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { imageQuality = [NSNumber numberWithInt:1]; - }else{ + } else { imageQuality = @([imageQuality floatValue] / 100); } @@ -310,7 +310,7 @@ - (void)saveImageWithOriginalImageData:(NSData *)originalImageData - (void)saveImageWithPickerInfo:(NSDictionary *)info image:(UIImage *)image - imageQuality:(NSNumber *)imageQuality{ + imageQuality:(NSNumber *)imageQuality { NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info image:image imageQuality:imageQuality]; From 064bcdfbd18990094236e472f8d0a8129f9b3132 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Wed, 24 Jul 2019 19:16:16 +0530 Subject: [PATCH 04/14] Code format --- .../ios/Classes/FLTImagePickerPhotoAssetUtil.m | 8 ++++++-- packages/image_picker/ios/Classes/ImagePickerPlugin.m | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m index 172ed1276fb1..1eae6be95396 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m @@ -49,7 +49,9 @@ + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData } } -+ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality { ++ (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info + image:(UIImage *)image + imageQuality:(NSNumber *)imageQuality { NSDictionary *metaData = info[UIImagePickerControllerMediaMetadata]; return [self saveImageWithMetaData:metaData image:image @@ -79,7 +81,9 @@ + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData [FLTImagePickerMetaDataUtil getNormalizedUIImageOrientationFromCGImagePropertyOrientation:orientation]]; - NSData *data = [FLTImagePickerMetaDataUtil convertImage:newImage usingType:type quality:imageQuality]; + NSData *data = [FLTImagePickerMetaDataUtil convertImage:newImage + usingType:type + quality:imageQuality]; if (metaData) { data = [FLTImagePickerMetaDataUtil updateMetaData:metaData toImage:data]; } diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index 301ddc2570a5..e25c1637353b 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -254,9 +254,9 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"]; if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { - imageQuality = [NSNumber numberWithInt:1]; + imageQuality = [NSNumber numberWithInt:1]; } else { - imageQuality = @([imageQuality floatValue] / 100); + imageQuality = @([imageQuality floatValue] / 100); } if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) { @@ -310,7 +310,7 @@ - (void)saveImageWithOriginalImageData:(NSData *)originalImageData - (void)saveImageWithPickerInfo:(NSDictionary *)info image:(UIImage *)image - imageQuality:(NSNumber *)imageQuality { + imageQuality:(NSNumber *)imageQuality { NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info image:image imageQuality:imageQuality]; From 968239785b0cb3a1b7a1a473d5f813ad9caa7252 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Wed, 24 Jul 2019 19:23:38 +0530 Subject: [PATCH 05/14] Code format --- .../ios/Classes/FLTImagePickerMetaDataUtil.m | 18 +++++++++--------- .../ios/Classes/FLTImagePickerPhotoAssetUtil.m | 6 +++++- .../ios/Classes/ImagePickerPlugin.m | 6 +++--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m index 120be9ed25dc..108b23de750c 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m @@ -64,15 +64,15 @@ + (NSData *)convertImage:(UIImage *)image usingType:(FLTImagePickerMIMEType)type quality:(nullable NSNumber *)quality { -// Commenting as of now as JPEG conversion is done by default -// if (quality && type != FLTImagePickerMIMETypeJPEG) { -// @throw [NSException -// exceptionWithName:@"flutter_image_picker_convert_image_exception" -// reason:[NSString stringWithFormat:@"quality is not available for type %@", -// [FLTImagePickerMetaDataUtil -// imageTypeSuffixFromType:type]] -// userInfo:nil]; -// } + // Commenting as of now as JPEG conversion is done by default + // if (quality && type != FLTImagePickerMIMETypeJPEG) { + // @throw [NSException + // exceptionWithName:@"flutter_image_picker_convert_image_exception" + // reason:[NSString stringWithFormat:@"quality is not available for type %@", + // [FLTImagePickerMetaDataUtil + // imageTypeSuffixFromType:type]] + // userInfo:nil]; + // } switch (type) { case FLTImagePickerMIMETypeJPEG: { diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m index 1eae6be95396..5f825e9bf826 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m @@ -45,7 +45,11 @@ + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData return [self saveImageWithMetaData:metaData gifInfo:gifInfo suffix:suffix]; } else { - return [self saveImageWithMetaData:metaData image:image suffix:suffix type:type imageQuality:imageQuality]; + return [self saveImageWithMetaData:metaData + image:image + suffix:suffix + type:type + imageQuality:imageQuality]; } } diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index e25c1637353b..6291857c95ae 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -311,9 +311,9 @@ - (void)saveImageWithOriginalImageData:(NSData *)originalImageData - (void)saveImageWithPickerInfo:(NSDictionary *)info image:(UIImage *)image imageQuality:(NSNumber *)imageQuality { - NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info - image:image - imageQuality:imageQuality]; + NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info + image:image + imageQuality:imageQuality]; [self handleSavedPath:savedPath]; } From 3b63af5f02bb963b8d46543d3ac61c436256192e Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Wed, 24 Jul 2019 19:33:29 +0530 Subject: [PATCH 06/14] Code format --- .../ios/Classes/FLTImagePickerMetaDataUtil.m | 18 +++++++++--------- .../ios/Classes/FLTImagePickerPhotoAssetUtil.m | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m index 108b23de750c..3be7f4db3eea 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m @@ -64,15 +64,15 @@ + (NSData *)convertImage:(UIImage *)image usingType:(FLTImagePickerMIMEType)type quality:(nullable NSNumber *)quality { - // Commenting as of now as JPEG conversion is done by default - // if (quality && type != FLTImagePickerMIMETypeJPEG) { - // @throw [NSException - // exceptionWithName:@"flutter_image_picker_convert_image_exception" - // reason:[NSString stringWithFormat:@"quality is not available for type %@", - // [FLTImagePickerMetaDataUtil - // imageTypeSuffixFromType:type]] - // userInfo:nil]; - // } + // Commenting as of now as JPEG conversion is done by default + // if (quality && type != FLTImagePickerMIMETypeJPEG) { + // @throw [NSException + // exceptionWithName:@"flutter_image_picker_convert_image_exception" + // reason:[NSString stringWithFormat:@"quality is not available for type %@", + // [FLTImagePickerMetaDataUtil + // imageTypeSuffixFromType:type]] + // userInfo:nil]; + // } switch (type) { case FLTImagePickerMIMETypeJPEG: { diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m index 5f825e9bf826..59e9d51b9ed8 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m @@ -50,7 +50,7 @@ + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData suffix:suffix type:type imageQuality:imageQuality]; - } + } } + (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info From 7dc8e963d2bb75255ff34dfef59d46f54db706bd Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Thu, 25 Jul 2019 00:39:24 +0530 Subject: [PATCH 07/14] Review changes --- .../plugins/imagepicker/ImagePickerDelegate.java | 5 ++++- .../io/flutter/plugins/imagepicker/ImageResizer.java | 6 ++++++ packages/image_picker/example/lib/main.dart | 3 +-- .../ios/Classes/FLTImagePickerMetaDataUtil.m | 12 +++--------- .../image_picker/ios/Classes/ImagePickerPlugin.m | 4 ++++ packages/image_picker/lib/image_picker.dart | 10 +--------- packages/image_picker/test/image_picker_test.dart | 12 ++++++------ 7 files changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index 448bfda98c72..874c32e7bc42 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -511,7 +511,10 @@ private void handleImageResult(String path, boolean shouldDeleteOriginalIfScaled if (methodCall != null) { Double maxWidth = methodCall.argument("maxWidth"); Double maxHeight = methodCall.argument("maxHeight"); - int imageQuality = methodCall.argument("imageQuality"); + int imageQuality = + methodCall.argument("imageQuality") == null + ? 100 + : (int) methodCall.argument("imageQuality"); String finalImagePath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality); diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java index 1bd1c9e92fd7..363bfec8281b 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java @@ -6,6 +6,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -93,6 +94,11 @@ private File resizedImage(String path, Double maxWidth, Double maxHeight, int im Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, width.intValue(), height.intValue(), false); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); boolean saveAsPNG = bmp.hasAlpha(); + if (saveAsPNG) { + Log.d( + "ImageResizer", + "image_picker: compressing is not supported for type PNG. Returning the image with original quality"); + } scaledBmp.compress( saveAsPNG ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, imageQuality, diff --git a/packages/image_picker/example/lib/main.dart b/packages/image_picker/example/lib/main.dart index ed0667004e01..066c12380b40 100755 --- a/packages/image_picker/example/lib/main.dart +++ b/packages/image_picker/example/lib/main.dart @@ -59,8 +59,7 @@ class _MyHomePageState extends State { }); } else { try { - _imageFile = - await ImagePicker.pickImage(source: source, imageQuality: 50); + _imageFile = await ImagePicker.pickImage(source: source); } catch (e) { _pickImageError = e; } diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m index 3be7f4db3eea..a3c626f526cb 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m @@ -64,15 +64,9 @@ + (NSData *)convertImage:(UIImage *)image usingType:(FLTImagePickerMIMEType)type quality:(nullable NSNumber *)quality { - // Commenting as of now as JPEG conversion is done by default - // if (quality && type != FLTImagePickerMIMETypeJPEG) { - // @throw [NSException - // exceptionWithName:@"flutter_image_picker_convert_image_exception" - // reason:[NSString stringWithFormat:@"quality is not available for type %@", - // [FLTImagePickerMetaDataUtil - // imageTypeSuffixFromType:type]] - // userInfo:nil]; - // } + if (quality && type != FLTImagePickerMIMETypeJPEG) { + NSLog(@"image_picker: compressing is not supported for type %@. Returning the image with original quality"); + } switch (type) { case FLTImagePickerMIMETypeJPEG: { diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index 6291857c95ae..da69e420d169 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -253,6 +253,10 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"]; NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"]; + if (![imageQuality isKindOfClass:[NSNumber class]]) { + imageQuality = @1; + } + if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { imageQuality = [NSNumber numberWithInt:1]; } else { diff --git a/packages/image_picker/lib/image_picker.dart b/packages/image_picker/lib/image_picker.dart index ed7cfb9fc499..3befcc76e5ed 100755 --- a/packages/image_picker/lib/image_picker.dart +++ b/packages/image_picker/lib/image_picker.dart @@ -44,6 +44,7 @@ class ImagePicker { double maxHeight, int imageQuality}) async { assert(source != null); + assert(imageQuality == null || (imageQuality >= 0 && imageQuality <= 100)); if (maxWidth != null && maxWidth < 0) { throw ArgumentError.value(maxWidth, 'maxWidth cannot be negative'); @@ -53,15 +54,6 @@ class ImagePicker { throw ArgumentError.value(maxHeight, 'maxHeight cannot be negative'); } - if (null == imageQuality) { - imageQuality = 100; - } - - if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) { - throw ArgumentError.value( - imageQuality, 'invalid imageQuality, must be between 0 and 100'); - } - final String path = await _channel.invokeMethod( 'pickImage', { diff --git a/packages/image_picker/test/image_picker_test.dart b/packages/image_picker/test/image_picker_test.dart index ea81c32b9142..7d962e6b916b 100644 --- a/packages/image_picker/test/image_picker_test.dart +++ b/packages/image_picker/test/image_picker_test.dart @@ -34,13 +34,13 @@ void main() { 'source': 0, 'maxWidth': null, 'maxHeight': null, - 'imageQuality': 100 + 'imageQuality': null }), isMethodCall('pickImage', arguments: { 'source': 1, 'maxWidth': null, 'maxHeight': null, - 'imageQuality': 100 + 'imageQuality': null }), ], ); @@ -78,25 +78,25 @@ void main() { 'source': 0, 'maxWidth': null, 'maxHeight': null, - 'imageQuality': 100 + 'imageQuality': null }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, - 'imageQuality': 100 + 'imageQuality': null }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, - 'imageQuality': 100 + 'imageQuality': null }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, - 'imageQuality': 100 + 'imageQuality': null }), isMethodCall('pickImage', arguments: { 'source': 0, From 53c39dd94b1b96885c12f13c9bd681cab13616e5 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Thu, 25 Jul 2019 01:17:44 +0530 Subject: [PATCH 08/14] Review changes --- .../flutter/plugins/imagepicker/ImagePickerDelegateTest.java | 4 ++-- .../image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m | 2 +- packages/image_picker/ios/Classes/ImagePickerPlugin.m | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index 380241c23fd5..8940738289fd 100644 --- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -26,7 +26,7 @@ public class ImagePickerDelegateTest { private static final double WIDTH = 10.0; private static final double HEIGHT = 10.0; - private static final double IMAGE_QUALITY = 70; + private static final int IMAGE_QUALITY = 70; @Mock Activity mockActivity; @Mock ImageResizer mockImageResizer; @@ -67,7 +67,7 @@ public void setUp() { .thenReturn("scaledPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, 0)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, null)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, 0)) .thenReturn("scaledPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, IMAGE_QUALITY)) .thenReturn("scaledPath"); diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m index a3c626f526cb..550243a0bda7 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m @@ -65,7 +65,7 @@ + (NSData *)convertImage:(UIImage *)image quality:(nullable NSNumber *)quality { if (quality && type != FLTImagePickerMIMETypeJPEG) { - NSLog(@"image_picker: compressing is not supported for type %@. Returning the image with original quality"); + NSLog(@"image_picker: compressing is not supported for type %@. Returning the image with original quality", [FLTImagePickerMetaDataUtil imageTypeSuffixFromType:type]); } switch (type) { diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index da69e420d169..975c47778bbc 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -255,9 +255,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker if (![imageQuality isKindOfClass:[NSNumber class]]) { imageQuality = @1; - } - - if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { + } else if (imageQuality.intValue < 0 || imageQuality.intValue > 100) { imageQuality = [NSNumber numberWithInt:1]; } else { imageQuality = @([imageQuality floatValue] / 100); From aae056e29fb75aa887fff0b55710dde2938035a9 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Thu, 25 Jul 2019 15:08:28 +0530 Subject: [PATCH 09/14] Updated pubspec and changelog, test cases --- packages/image_picker/CHANGELOG.md | 5 +++++ .../flutter/plugins/imagepicker/ImagePickerDelegate.java | 7 +++++-- .../plugins/imagepicker/ImagePickerDelegateTest.java | 6 ++---- .../image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m | 5 +++-- packages/image_picker/pubspec.yaml | 2 +- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index 44c8cc9dd01e..642aa7169fb2 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.6.0+18 + +* New feature : Get images with custom quality. While picking images, user can pass `imageQuality` +parameter to compress image. + ## 0.6.0+17 * iOS: Fix a crash when user captures image from the camera with devices under iOS 11. diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index 874c32e7bc42..b9481d3fe305 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -210,7 +210,10 @@ void retrieveLostImage(MethodChannel.Result result) { if (path != null) { Double maxWidth = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_WIDTH); Double maxHeight = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_HEIGHT); - int imageQuality = (int) resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); + int imageQuality = + resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY) == null + ? 100 + : (int) resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); String newPath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality); resultMap.put(ImagePickerCache.MAP_KEY_PATH, newPath); @@ -522,7 +525,7 @@ private void handleImageResult(String path, boolean shouldDeleteOriginalIfScaled finishWithSuccess(finalImagePath); //delete original file if scaled - if (!finalImagePath.equals(path) && shouldDeleteOriginalIfScaled) { + if (finalImagePath != null && !finalImagePath.equals(path) && shouldDeleteOriginalIfScaled) { new File(path).delete(); } } else { diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index 8940738289fd..cd0191b5bd26 100644 --- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -65,11 +65,9 @@ public void setUp() { .thenReturn("originalPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, IMAGE_QUALITY)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, 0)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, -1)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, 0)) - .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, IMAGE_QUALITY)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, -1)) .thenReturn("scaledPath"); mockFileUriResolver = new MockFileUriResolver(); diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m index 550243a0bda7..a789853d32aa 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m @@ -63,9 +63,10 @@ + (NSData *)updateMetaData:(NSDictionary *)metaData toImage:(NSData *)imageData + (NSData *)convertImage:(UIImage *)image usingType:(FLTImagePickerMIMEType)type quality:(nullable NSNumber *)quality { - if (quality && type != FLTImagePickerMIMETypeJPEG) { - NSLog(@"image_picker: compressing is not supported for type %@. Returning the image with original quality", [FLTImagePickerMetaDataUtil imageTypeSuffixFromType:type]); + NSLog(@"image_picker: compressing is not supported for type %@. Returning the image with " + @"original quality", + [FLTImagePickerMetaDataUtil imageTypeSuffixFromType:type]); } switch (type) { diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml index 721e6abdfbeb..9da16aa6edaf 100755 --- a/packages/image_picker/pubspec.yaml +++ b/packages/image_picker/pubspec.yaml @@ -6,7 +6,7 @@ authors: - Rhodes Davis Jr. homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker -version: 0.6.0+17 +version: 0.6.0+18 flutter: plugin: From 56a074400a6beeca18d8cf4b560efcf7c78eb592 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Thu, 25 Jul 2019 22:22:34 +0530 Subject: [PATCH 10/14] Updated pubspec and changelog --- packages/image_picker/CHANGELOG.md | 2 +- packages/image_picker/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index 642aa7169fb2..5d45070e44aa 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.6.0+18 +## 0.6.1 * New feature : Get images with custom quality. While picking images, user can pass `imageQuality` parameter to compress image. diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml index 9da16aa6edaf..549609f3a4e4 100755 --- a/packages/image_picker/pubspec.yaml +++ b/packages/image_picker/pubspec.yaml @@ -6,7 +6,7 @@ authors: - Rhodes Davis Jr. homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker -version: 0.6.0+18 +version: 0.6.1 flutter: plugin: From 983e38bbf491f039d803900564d3d997d77ceb02 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Tue, 30 Jul 2019 13:47:53 +0530 Subject: [PATCH 11/14] Updated test cases, resolved conflicts with latest commit --- packages/image_picker/CHANGELOG.md | 12 ++ .../plugins/imagepicker/ImagePickerCache.java | 128 ++++++++---------- .../imagepicker/ImagePickerDelegate.java | 59 ++++---- .../imagepicker/ImagePickerPlugin.java | 4 +- .../imagepicker/ImagePickerDelegateTest.java | 11 +- 5 files changed, 112 insertions(+), 102 deletions(-) diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index 5d45070e44aa..a8e371c48072 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -3,6 +3,18 @@ * New feature : Get images with custom quality. While picking images, user can pass `imageQuality` parameter to compress image. +## 0.6.0+20 + +* Android: Migrated information cache methods to use instance methods. + +## 0.6.0+19 + +* Android: Fix memory leak due not unregistering ActivityLifecycleCallbacks. + +## 0.6.0+18 + +* Fix video play in example and update video_player plugin dependency. + ## 0.6.0+17 * iOS: Fix a crash when user captures image from the camera with devices under iOS 11. diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java index 7bc1537de5da..9b3e3933fb69 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java @@ -4,7 +4,6 @@ package io.flutter.plugins.imagepicker; -import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.net.Uri; @@ -30,21 +29,20 @@ class ImagePickerCache { "flutter_image_picker_error_message"; private static final String SHARED_PREFERENCE_MAX_WIDTH_KEY = "flutter_image_picker_max_width"; private static final String SHARED_PREFERENCE_MAX_HEIGHT_KEY = "flutter_image_picker_max_height"; + private static final String SHARED_PREFERENCE_IMAGE_QUALITY_KEY = + "flutter_image_picker_image_quality"; private static final String SHARED_PREFERENCE_TYPE_KEY = "flutter_image_picker_type"; private static final String SHARED_PREFERENCE_PENDING_IMAGE_URI_PATH_KEY = "flutter_image_picker_pending_image_uri"; private static final String SHARED_PREFERENCES_NAME = "flutter_image_picker_shared_preference"; - private static SharedPreferences getFilePref; + private SharedPreferences prefs; - static void setUpWithActivity(Activity activity) { - getFilePref = - activity - .getApplicationContext() - .getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + ImagePickerCache(Context context) { + prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); } - static void saveTypeWithMethodCallName(String methodCallName) { + void saveTypeWithMethodCallName(String methodCallName) { if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_IMAGE)) { setType("image"); } else if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_VIDEO)) { @@ -52,57 +50,50 @@ static void saveTypeWithMethodCallName(String methodCallName) { } } - private static void setType(String type) { - if (getFilePref == null) { - return; - } - getFilePref.edit().putString(SHARED_PREFERENCE_TYPE_KEY, type).apply(); + private void setType(String type) { + + prefs.edit().putString(SHARED_PREFERENCE_TYPE_KEY, type).apply(); } - static void saveDemensionWithMethodCall(MethodCall methodCall) { - Double maxWidth = methodCall.argument("maxWidth"); - Double maxHeight = methodCall.argument("maxHeight"); - setMaxDimension(maxWidth, maxHeight); + void saveDimensionWithMethodCall(MethodCall methodCall) { + Double maxWidth = methodCall.argument(MAP_KEY_MAX_WIDTH); + Double maxHeight = methodCall.argument(MAP_KEY_MAX_HEIGHT); + int imageQuality = + methodCall.argument(MAP_KEY_IMAGE_QUALITY) == null + ? 100 + : (int) methodCall.argument(MAP_KEY_IMAGE_QUALITY); + + setMaxDimension(maxWidth, maxHeight, imageQuality); } - private static void setMaxDimension(Double maxWidth, Double maxHeight) { - if (getFilePref == null) { - return; - } + private void setMaxDimension(Double maxWidth, Double maxHeight, int imageQuality) { - SharedPreferences.Editor editor = getFilePref.edit(); + SharedPreferences.Editor editor = prefs.edit(); if (maxWidth != null) { editor.putLong(SHARED_PREFERENCE_MAX_WIDTH_KEY, Double.doubleToRawLongBits(maxWidth)); } if (maxHeight != null) { editor.putLong(SHARED_PREFERENCE_MAX_HEIGHT_KEY, Double.doubleToRawLongBits(maxHeight)); } + if (imageQuality > -1 && imageQuality < 101) { + editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, imageQuality); + } editor.apply(); } - static void savePendingCameraMediaUriPath(Uri uri) { - if (getFilePref == null) { - return; - } - getFilePref - .edit() - .putString(SHARED_PREFERENCE_PENDING_IMAGE_URI_PATH_KEY, uri.getPath()) - .apply(); + void savePendingCameraMediaUriPath(Uri uri) { + prefs.edit().putString(SHARED_PREFERENCE_PENDING_IMAGE_URI_PATH_KEY, uri.getPath()).apply(); } - static String retrievePendingCameraMediaUriPath() { - if (getFilePref == null) { - return null; - } - return getFilePref.getString(SHARED_PREFERENCE_PENDING_IMAGE_URI_PATH_KEY, ""); + String retrievePendingCameraMediaUriPath() { + + return prefs.getString(SHARED_PREFERENCE_PENDING_IMAGE_URI_PATH_KEY, ""); } - static void saveResult( + void saveResult( @Nullable String path, @Nullable String errorCode, @Nullable String errorMessage) { - if (getFilePref == null) { - return; - } - SharedPreferences.Editor editor = getFilePref.edit(); + + SharedPreferences.Editor editor = prefs.edit(); if (path != null) { editor.putString(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, path); } @@ -115,50 +106,47 @@ static void saveResult( editor.apply(); } - static void clear() { - if (getFilePref == null) { - return; - } - getFilePref.edit().clear().apply(); + void clear() { + prefs.edit().clear().apply(); } - static Map getCacheMap() { - if (getFilePref == null) { - return new HashMap<>(); - } + Map getCacheMap() { + Map resultMap = new HashMap<>(); - Boolean hasData = false; + boolean hasData = false; - if (getFilePref.contains(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY)) { - resultMap.put(MAP_KEY_PATH, getFilePref.getString(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, "")); + if (prefs.contains(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY)) { + final String imagePathValue = prefs.getString(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, ""); + resultMap.put(MAP_KEY_PATH, imagePathValue); hasData = true; } - if (getFilePref.contains(SHARED_PREFERENCE_ERROR_CODE_KEY)) { - resultMap.put( - MAP_KEY_ERROR_CODE, getFilePref.getString(SHARED_PREFERENCE_ERROR_CODE_KEY, "")); + if (prefs.contains(SHARED_PREFERENCE_ERROR_CODE_KEY)) { + final String errorCodeValue = prefs.getString(SHARED_PREFERENCE_ERROR_CODE_KEY, ""); + resultMap.put(MAP_KEY_ERROR_CODE, errorCodeValue); hasData = true; - if (getFilePref.contains(SHARED_PREFERENCE_ERROR_MESSAGE_KEY)) { - resultMap.put( - MAP_KEY_ERROR_MESSAGE, getFilePref.getString(SHARED_PREFERENCE_ERROR_MESSAGE_KEY, "")); + if (prefs.contains(SHARED_PREFERENCE_ERROR_MESSAGE_KEY)) { + final String errorMessageValue = prefs.getString(SHARED_PREFERENCE_ERROR_MESSAGE_KEY, ""); + resultMap.put(MAP_KEY_ERROR_MESSAGE, errorMessageValue); } } if (hasData) { - if (getFilePref.contains(SHARED_PREFERENCE_TYPE_KEY)) { - resultMap.put(MAP_KEY_TYPE, getFilePref.getString(SHARED_PREFERENCE_TYPE_KEY, "")); + if (prefs.contains(SHARED_PREFERENCE_TYPE_KEY)) { + final String typeValue = prefs.getString(SHARED_PREFERENCE_TYPE_KEY, ""); + resultMap.put(MAP_KEY_TYPE, typeValue); } - - if (getFilePref.contains(SHARED_PREFERENCE_MAX_WIDTH_KEY)) { - resultMap.put( - MAP_KEY_MAX_WIDTH, - Double.longBitsToDouble(getFilePref.getLong(SHARED_PREFERENCE_MAX_WIDTH_KEY, 0))); + if (prefs.contains(SHARED_PREFERENCE_MAX_WIDTH_KEY)) { + final long maxWidthValue = prefs.getLong(SHARED_PREFERENCE_MAX_WIDTH_KEY, 0); + resultMap.put(MAP_KEY_MAX_WIDTH, Double.longBitsToDouble(maxWidthValue)); } - - if (getFilePref.contains(SHARED_PREFERENCE_MAX_HEIGHT_KEY)) { - resultMap.put( - MAP_KEY_MAX_HEIGHT, - Double.longBitsToDouble(getFilePref.getLong(SHARED_PREFERENCE_MAX_HEIGHT_KEY, 0))); + if (prefs.contains(SHARED_PREFERENCE_MAX_HEIGHT_KEY)) { + final long maxHeighValue = prefs.getLong(SHARED_PREFERENCE_MAX_HEIGHT_KEY, 0); + resultMap.put(MAP_KEY_MAX_HEIGHT, Double.longBitsToDouble(maxHeighValue)); + } + if (prefs.contains(SHARED_PREFERENCE_IMAGE_QUALITY_KEY)) { + final int imageQuality = prefs.getInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, 100); + resultMap.put(MAP_KEY_MAX_HEIGHT, imageQuality); } } diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index b9481d3fe305..5ab12636a509 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -80,6 +80,7 @@ public class ImagePickerDelegate private final Activity activity; private final File externalFilesDirectory; private final ImageResizer imageResizer; + private final ImagePickerCache cache; private final PermissionManager permissionManager; private final IntentResolver intentResolver; private final FileUriResolver fileUriResolver; @@ -112,13 +113,17 @@ interface OnPathReadyListener { private MethodCall methodCall; public ImagePickerDelegate( - final Activity activity, File externalFilesDirectory, ImageResizer imageResizer) { + final Activity activity, + File externalFilesDirectory, + ImageResizer imageResizer, + final ImagePickerCache cache) { this( activity, externalFilesDirectory, imageResizer, null, null, + cache, new PermissionManager() { @Override public boolean isPermissionGranted(String permissionName) { @@ -171,15 +176,16 @@ public void onScanCompleted(String path, Uri uri) { */ @VisibleForTesting ImagePickerDelegate( - Activity activity, - File externalFilesDirectory, - ImageResizer imageResizer, - MethodChannel.Result result, - MethodCall methodCall, - PermissionManager permissionManager, - IntentResolver intentResolver, - FileUriResolver fileUriResolver, - FileUtils fileUtils) { + final Activity activity, + final File externalFilesDirectory, + final ImageResizer imageResizer, + final MethodChannel.Result result, + final MethodCall methodCall, + final ImagePickerCache cache, + final PermissionManager permissionManager, + final IntentResolver intentResolver, + final FileUriResolver fileUriResolver, + final FileUtils fileUtils) { this.activity = activity; this.externalFilesDirectory = externalFilesDirectory; this.imageResizer = imageResizer; @@ -190,6 +196,7 @@ public void onScanCompleted(String path, Uri uri) { this.intentResolver = intentResolver; this.fileUriResolver = fileUriResolver; this.fileUtils = fileUtils; + this.cache = cache; } void saveStateBeforeResult() { @@ -197,33 +204,33 @@ void saveStateBeforeResult() { return; } - ImagePickerCache.saveTypeWithMethodCallName(methodCall.method); - ImagePickerCache.saveDemensionWithMethodCall(methodCall); + cache.saveTypeWithMethodCallName(methodCall.method); + cache.saveDimensionWithMethodCall(methodCall); if (pendingCameraMediaUri != null) { - ImagePickerCache.savePendingCameraMediaUriPath(pendingCameraMediaUri); + cache.savePendingCameraMediaUriPath(pendingCameraMediaUri); } } void retrieveLostImage(MethodChannel.Result result) { - Map resultMap = ImagePickerCache.getCacheMap(); - String path = (String) resultMap.get(ImagePickerCache.MAP_KEY_PATH); + Map resultMap = cache.getCacheMap(); + String path = (String) resultMap.get(cache.MAP_KEY_PATH); if (path != null) { - Double maxWidth = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_WIDTH); - Double maxHeight = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_HEIGHT); + Double maxWidth = (Double) resultMap.get(cache.MAP_KEY_MAX_WIDTH); + Double maxHeight = (Double) resultMap.get(cache.MAP_KEY_MAX_HEIGHT); int imageQuality = - resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY) == null + resultMap.get(cache.MAP_KEY_IMAGE_QUALITY) == null ? 100 - : (int) resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); + : (int) resultMap.get(cache.MAP_KEY_IMAGE_QUALITY); String newPath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality); - resultMap.put(ImagePickerCache.MAP_KEY_PATH, newPath); + resultMap.put(cache.MAP_KEY_PATH, newPath); } if (resultMap.isEmpty()) { result.success(null); } else { result.success(resultMap); } - ImagePickerCache.clear(); + cache.clear(); } public void chooseVideoFromGallery(MethodCall methodCall, MethodChannel.Result result) { @@ -477,7 +484,7 @@ private void handleCaptureImageResult(int resultCode) { fileUriResolver.getFullImagePath( pendingCameraMediaUri != null ? pendingCameraMediaUri - : Uri.parse(ImagePickerCache.retrievePendingCameraMediaUriPath()), + : Uri.parse(cache.retrievePendingCameraMediaUriPath()), new OnPathReadyListener() { @Override public void onPathReady(String path) { @@ -496,7 +503,7 @@ private void handleCaptureVideoResult(int resultCode) { fileUriResolver.getFullImagePath( pendingCameraMediaUri != null ? pendingCameraMediaUri - : Uri.parse(ImagePickerCache.retrievePendingCameraMediaUriPath()), + : Uri.parse(cache.retrievePendingCameraMediaUriPath()), new OnPathReadyListener() { @Override public void onPathReady(String path) { @@ -547,14 +554,14 @@ private boolean setPendingMethodCallAndResult( pendingResult = result; // Clean up cache if a new image picker is launched. - ImagePickerCache.clear(); + cache.clear(); return true; } private void finishWithSuccess(String imagePath) { if (pendingResult == null) { - ImagePickerCache.saveResult(imagePath, null, null); + cache.saveResult(imagePath, null, null); return; } pendingResult.success(imagePath); @@ -567,7 +574,7 @@ private void finishWithAlreadyActiveError(MethodChannel.Result result) { private void finishWithError(String errorCode, String errorMessage) { if (pendingResult == null) { - ImagePickerCache.saveResult(null, errorCode, errorMessage); + cache.saveResult(null, errorCode, errorMessage); return; } pendingResult.error(errorCode, errorMessage, null); diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java index 371a258966c0..923616e1b4ac 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java @@ -37,7 +37,7 @@ public static void registerWith(PluginRegistry.Registrar registrar) { // we stop the registering process immediately because the ImagePicker requires an activity. return; } - ImagePickerCache.setUpWithActivity(registrar.activity()); + final ImagePickerCache cache = new ImagePickerCache(registrar.activity()); final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL); @@ -46,7 +46,7 @@ public static void registerWith(PluginRegistry.Registrar registrar) { final ExifDataCopier exifDataCopier = new ExifDataCopier(); final ImageResizer imageResizer = new ImageResizer(externalFilesDirectory, exifDataCopier); final ImagePickerDelegate delegate = - new ImagePickerDelegate(registrar.activity(), externalFilesDirectory, imageResizer); + new ImagePickerDelegate(registrar.activity(), externalFilesDirectory, imageResizer, cache); registrar.addActivityResultListener(delegate); registrar.addRequestPermissionsResultListener(delegate); diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index cd0191b5bd26..60e1167cd87a 100644 --- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -26,7 +26,7 @@ public class ImagePickerDelegateTest { private static final double WIDTH = 10.0; private static final double HEIGHT = 10.0; - private static final int IMAGE_QUALITY = 70; + private static final int IMAGE_QUALITY = 100; @Mock Activity mockActivity; @Mock ImageResizer mockImageResizer; @@ -36,6 +36,7 @@ public class ImagePickerDelegateTest { @Mock ImagePickerDelegate.IntentResolver mockIntentResolver; @Mock FileUtils mockFileUtils; @Mock Intent mockIntent; + @Mock ImagePickerCache cache; ImagePickerDelegate.FileUriResolver mockFileUriResolver; @@ -61,13 +62,13 @@ public void setUp() { when(mockFileUtils.getPathFromUri(any(Context.class), any(Uri.class))) .thenReturn("pathFromUri"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, -1)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, IMAGE_QUALITY)) .thenReturn("originalPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, IMAGE_QUALITY)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, -1)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, IMAGE_QUALITY)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, -1)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, IMAGE_QUALITY)) .thenReturn("scaledPath"); mockFileUriResolver = new MockFileUriResolver(); @@ -377,6 +378,7 @@ private ImagePickerDelegate createDelegate() { mockImageResizer, null, null, + cache, mockPermissionManager, mockIntentResolver, mockFileUriResolver, @@ -390,6 +392,7 @@ private ImagePickerDelegate createDelegateWithPendingResultAndMethodCall() { mockImageResizer, mockResult, mockMethodCall, + cache, mockPermissionManager, mockIntentResolver, mockFileUriResolver, From bc6ce98b78b6add08f2bfa9770f313edbe962382 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Tue, 30 Jul 2019 14:45:30 +0530 Subject: [PATCH 12/14] Added checks in ImagePickerCache for imageQuality --- .../io/flutter/plugins/imagepicker/ImagePickerCache.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java index 9b3e3933fb69..a9dc35a8f4a2 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java @@ -77,6 +77,8 @@ private void setMaxDimension(Double maxWidth, Double maxHeight, int imageQuality } if (imageQuality > -1 && imageQuality < 101) { editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, imageQuality); + }else{ + editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, 100); } editor.apply(); } @@ -141,12 +143,14 @@ Map getCacheMap() { resultMap.put(MAP_KEY_MAX_WIDTH, Double.longBitsToDouble(maxWidthValue)); } if (prefs.contains(SHARED_PREFERENCE_MAX_HEIGHT_KEY)) { - final long maxHeighValue = prefs.getLong(SHARED_PREFERENCE_MAX_HEIGHT_KEY, 0); - resultMap.put(MAP_KEY_MAX_HEIGHT, Double.longBitsToDouble(maxHeighValue)); + final long maxHeightValue = prefs.getLong(SHARED_PREFERENCE_MAX_HEIGHT_KEY, 0); + resultMap.put(MAP_KEY_MAX_HEIGHT, Double.longBitsToDouble(maxHeightValue)); } if (prefs.contains(SHARED_PREFERENCE_IMAGE_QUALITY_KEY)) { final int imageQuality = prefs.getInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, 100); resultMap.put(MAP_KEY_MAX_HEIGHT, imageQuality); + }else{ + resultMap.put(MAP_KEY_MAX_HEIGHT, 100); } } From 9efaf38ce9b4c0a28944764875fec9b160d061d8 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Tue, 30 Jul 2019 14:57:52 +0530 Subject: [PATCH 13/14] Code format --- .../java/io/flutter/plugins/imagepicker/ImagePickerCache.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java index f43c5758a118..6e5121f10200 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java @@ -76,7 +76,7 @@ private void setMaxDimension(Double maxWidth, Double maxHeight, int imageQuality } if (imageQuality > -1 && imageQuality < 101) { editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, imageQuality); - }else{ + } else { editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, 100); } editor.apply(); @@ -148,7 +148,7 @@ Map getCacheMap() { if (prefs.contains(SHARED_PREFERENCE_IMAGE_QUALITY_KEY)) { final int imageQuality = prefs.getInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, 100); resultMap.put(MAP_KEY_MAX_HEIGHT, imageQuality); - }else{ + } else { resultMap.put(MAP_KEY_MAX_HEIGHT, 100); } } From 4f09e62630f8805c2cd96058f5605f9e928dbea1 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 30 Jul 2019 09:11:16 -0700 Subject: [PATCH 14/14] Update image_picker.dart --- packages/image_picker/lib/image_picker.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/image_picker/lib/image_picker.dart b/packages/image_picker/lib/image_picker.dart index 3befcc76e5ed..a6ca94713ee3 100755 --- a/packages/image_picker/lib/image_picker.dart +++ b/packages/image_picker/lib/image_picker.dart @@ -26,15 +26,17 @@ class ImagePicker { /// Returns a [File] object pointing to the image that was picked. /// - /// The [source] argument controls where the image comes from. This can + /// The `source` argument controls where the image comes from. This can /// be either [ImageSource.camera] or [ImageSource.gallery]. /// - /// If specified, the image will be at most [maxWidth] wide and - /// [maxHeight] tall. Otherwise the image will be returned at it's + /// If specified, the image will be at most `maxWidth` wide and + /// `maxHeight` tall. Otherwise the image will be returned at it's /// original width and height. - /// The [imageQuality] argument resize the image as per the input, ranging from 0-100 compression. - /// 0 meaning compress for small size, 100 meaning compress for max quality. - /// Some formats, like PNG which is loss less, will ignore the quality setting + /// The `imageQuality` argument modifies the quality of the image, ranging from 0-100 + /// where 100 is the original/max quality. If `imageQuality` is null, the image with + /// the original quality will be returned. Compression is only supportted for certain + /// image types such as JPEG. If compression is not supported for the image that is picked, + /// an warning message will be logged. /// /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost /// in this call. You can then call [retrieveLostData] when your app relaunches to retrieve the lost data.