diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md index e7048c371a95..bd0a7a06b4fc 100644 --- a/packages/image_picker/image_picker/CHANGELOG.md +++ b/packages/image_picker/image_picker/CHANGELOG.md @@ -1,6 +1,7 @@ -## NEXT +## 0.8.3 * Move `ImagePickerFromLimitedGalleryUITests` to `RunnerUITests` target. +* Improved handling of bad image data when applying metadata changes on iOS. ## 0.8.2 @@ -53,8 +54,8 @@ see: [#84634](https://github.com/flutter/flutter/issues/84634). ## 0.8.0 * BREAKING CHANGE: Changed storage location for captured images and videos to internal cache on Android, -to comply with new Google Play storage requirements. This means developers are responsible for moving -the image or video to a different location in case more permanent storage is required. Other applications +to comply with new Google Play storage requirements. This means developers are responsible for moving +the image or video to a different location in case more permanent storage is required. Other applications will no longer be able to access images or videos captured unless they are moved to a publicly accessible location. * Updated Mockito to fix Android tests. diff --git a/packages/image_picker/image_picker/example/ios/RunnerTests/MetaDataUtilTests.m b/packages/image_picker/image_picker/example/ios/RunnerTests/MetaDataUtilTests.m index e1dbfad77b5d..54f9469f2053 100644 --- a/packages/image_picker/image_picker/example/ios/RunnerTests/MetaDataUtilTests.m +++ b/packages/image_picker/image_picker/example/ios/RunnerTests/MetaDataUtilTests.m @@ -60,7 +60,7 @@ - (void)testWriteMetaData { NSString *tmpFile = [NSString stringWithFormat:@"image_picker_test.jpg"]; NSString *tmpDirectory = NSTemporaryDirectory(); NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile]; - NSData *newData = [FLTImagePickerMetaDataUtil updateMetaData:metaData toImage:dataJPG]; + NSData *newData = [FLTImagePickerMetaDataUtil imageFromImage:dataJPG withMetaData:metaData]; if ([[NSFileManager defaultManager] createFileAtPath:tmpPath contents:newData attributes:nil]) { NSData *savedTmpImageData = [NSData dataWithContentsOfFile:tmpPath]; NSDictionary *tmpMetaData = @@ -71,6 +71,14 @@ - (void)testWriteMetaData { } } +- (void)testUpdateMetaDataBadData { + NSData *imageData = [NSData data]; + + NSDictionary *metaData = [FLTImagePickerMetaDataUtil getMetaDataFromImageData:imageData]; + NSData *newData = [FLTImagePickerMetaDataUtil imageFromImage:imageData withMetaData:metaData]; + XCTAssertNil(newData); +} + - (void)testConvertImageToData { UIImage *imageJPG = [UIImage imageWithData:ImagePickerTestImages.JPGTestData]; NSData *convertedDataJPG = [FLTImagePickerMetaDataUtil convertImage:imageJPG diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h index d5a20ffc6d2e..72a36a56d57d 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h @@ -27,7 +27,11 @@ extern const FLTImagePickerMIMEType kFLTImagePickerMIMETypeDefault; + (NSDictionary *)getMetaDataFromImageData:(NSData *)imageData; -+ (NSData *)updateMetaData:(NSDictionary *)metaData toImage:(NSData *)imageData; +// Creates and returns data for a new image based on imageData, but with the +// given metadata. +// +// If creating a new image fails, returns nil. ++ (nullable NSData *)imageFromImage:(NSData *)imageData withMetaData:(NSDictionary *)metadata; // Converting UIImage to a NSData with the type proveide. // diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m index 1419584a4675..45bcaa7191f7 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m @@ -49,16 +49,27 @@ + (NSDictionary *)getMetaDataFromImageData:(NSData *)imageData { return metadata; } -+ (NSData *)updateMetaData:(NSDictionary *)metaData toImage:(NSData *)imageData { - NSMutableData *mutableData = [NSMutableData data]; - CGImageSourceRef cgImage = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); - CGImageDestinationRef destination = CGImageDestinationCreateWithData( - (__bridge CFMutableDataRef)mutableData, CGImageSourceGetType(cgImage), 1, nil); - CGImageDestinationAddImageFromSource(destination, cgImage, 0, (__bridge CFDictionaryRef)metaData); ++ (NSData *)imageFromImage:(NSData *)imageData withMetaData:(NSDictionary *)metadata { + NSMutableData *targetData = [NSMutableData data]; + CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); + if (source == NULL) { + return nil; + } + CGImageDestinationRef destination = NULL; + CFStringRef sourceType = CGImageSourceGetType(source); + if (sourceType != NULL) { + destination = + CGImageDestinationCreateWithData((__bridge CFMutableDataRef)targetData, sourceType, 1, nil); + } + if (destination == NULL) { + CFRelease(source); + return nil; + } + CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)metadata); CGImageDestinationFinalize(destination); - CFRelease(cgImage); + CFRelease(source); CFRelease(destination); - return mutableData; + return targetData; } + (NSData *)convertImage:(UIImage *)image diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m index ab881790d5ab..4c705fe54350 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m @@ -86,7 +86,11 @@ + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData usingType:type quality:imageQuality]; if (metaData) { - data = [FLTImagePickerMetaDataUtil updateMetaData:metaData toImage:data]; + NSData *updatedData = [FLTImagePickerMetaDataUtil imageFromImage:data withMetaData:metaData]; + // If updating the metadata fails, just save the original. + if (updatedData) { + data = updatedData; + } } return [self createFile:data suffix:suffix]; diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml index e5ecfeb22232..f56250f53715 100755 --- a/packages/image_picker/image_picker/pubspec.yaml +++ b/packages/image_picker/image_picker/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for selecting images from the Android and iOS image library, and taking new pictures with the camera. repository: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.2 +version: 0.8.3 environment: sdk: ">=2.12.0 <3.0.0"