[image_picker] Improve image_picker for iOS to handle more image types (#6812)
* Improve image picker for ios to handle more image types
* Update release info
* different svg, remove raw test
* change pro raw image
* change pro raw image
* add error log
* fix formatting
* fix image identifiers in test
* get image type identifier from itemProvider in test
diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md
index 986f5c0..bff6dd7 100644
--- a/packages/image_picker/image_picker_ios/CHANGELOG.md
+++ b/packages/image_picker/image_picker_ios/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.8.6+2
+
+* Fixes issue where selectable images of certain types (such as ProRAW images) could not be loaded.
+
## 0.8.6+1
* Fixes issue with crashing the app when picking images with PHPicker without providing `Photo Library Usage` permission.
diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj
index 2847bfd..2c97bd1 100644
--- a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj
@@ -18,6 +18,20 @@
680049382280F2B9006DD6AB /* pngImage.png in Resources */ = {isa = PBXBuildFile; fileRef = 680049352280F2B8006DD6AB /* pngImage.png */; };
680049392280F2B9006DD6AB /* jpgImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 680049362280F2B8006DD6AB /* jpgImage.jpg */; };
6801C8392555D726009DAF8D /* ImagePickerFromGalleryUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6801C8382555D726009DAF8D /* ImagePickerFromGalleryUITests.m */; };
+ 7865C5E12941326F0010E17F /* bmpImage.bmp in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E02941326F0010E17F /* bmpImage.bmp */; };
+ 7865C5E22941326F0010E17F /* bmpImage.bmp in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E02941326F0010E17F /* bmpImage.bmp */; };
+ 7865C5E4294132D50010E17F /* svgImage.svg in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E3294132D50010E17F /* svgImage.svg */; };
+ 7865C5E5294132D50010E17F /* svgImage.svg in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E3294132D50010E17F /* svgImage.svg */; };
+ 7865C5E72941374F0010E17F /* heicImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E62941374F0010E17F /* heicImage.heic */; };
+ 7865C5E82941374F0010E17F /* heicImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E62941374F0010E17F /* heicImage.heic */; };
+ 7865C5EA294137960010E17F /* icoImage.ico in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E9294137960010E17F /* icoImage.ico */; };
+ 7865C5EB294137960010E17F /* icoImage.ico in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E9294137960010E17F /* icoImage.ico */; };
+ 7865C5ED294137AB0010E17F /* tiffImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5EC294137AB0010E17F /* tiffImage.tiff */; };
+ 7865C5EE294137AB0010E17F /* tiffImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5EC294137AB0010E17F /* tiffImage.tiff */; };
+ 7865C5FC294157BC0010E17F /* icnsImage.icns in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FB294157BB0010E17F /* icnsImage.icns */; };
+ 7865C5FD294157BC0010E17F /* icnsImage.icns in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FB294157BB0010E17F /* icnsImage.icns */; };
+ 7865C5FF294252A60010E17F /* proRawImage.dng in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FE294252A60010E17F /* proRawImage.dng */; };
+ 7865C600294252A60010E17F /* proRawImage.dng in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FE294252A60010E17F /* proRawImage.dng */; };
86430DF9272D71E9002D9D6C /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; };
86E9A893272754860017E6E0 /* PickerSaveImageToPathOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 86E9A892272754860017E6E0 /* PickerSaveImageToPathOperationTests.m */; };
86E9A894272754A30017E6E0 /* webpImage.webp in Resources */ = {isa = PBXBuildFile; fileRef = 86E9A88F272747B90017E6E0 /* webpImage.webp */; };
@@ -81,6 +95,13 @@
6801C83A2555D726009DAF8D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
68B9AF71243E4B3F00927CE4 /* ImagePickerPluginTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImagePickerPluginTests.m; sourceTree = "<group>"; };
68F4B463228B3AB500C25614 /* PhotoAssetUtilTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PhotoAssetUtilTests.m; sourceTree = "<group>"; };
+ 7865C5E02941326F0010E17F /* bmpImage.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = bmpImage.bmp; sourceTree = "<group>"; };
+ 7865C5E3294132D50010E17F /* svgImage.svg */ = {isa = PBXFileReference; lastKnownFileType = text; path = svgImage.svg; sourceTree = "<group>"; };
+ 7865C5E62941374F0010E17F /* heicImage.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = heicImage.heic; sourceTree = "<group>"; };
+ 7865C5E9294137960010E17F /* icoImage.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = icoImage.ico; sourceTree = "<group>"; };
+ 7865C5EC294137AB0010E17F /* tiffImage.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = tiffImage.tiff; sourceTree = "<group>"; };
+ 7865C5FB294157BB0010E17F /* icnsImage.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icnsImage.icns; sourceTree = "<group>"; };
+ 7865C5FE294252A60010E17F /* proRawImage.dng */ = {isa = PBXFileReference; lastKnownFileType = file; path = proRawImage.dng; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -152,6 +173,13 @@
9FC8F0E8229FA49E00C8D58F /* gifImage.gif */,
680049362280F2B8006DD6AB /* jpgImage.jpg */,
680049352280F2B8006DD6AB /* pngImage.png */,
+ 7865C5E02941326F0010E17F /* bmpImage.bmp */,
+ 7865C5E62941374F0010E17F /* heicImage.heic */,
+ 7865C5FB294157BB0010E17F /* icnsImage.icns */,
+ 7865C5E9294137960010E17F /* icoImage.ico */,
+ 7865C5FE294252A60010E17F /* proRawImage.dng */,
+ 7865C5E3294132D50010E17F /* svgImage.svg */,
+ 7865C5EC294137AB0010E17F /* tiffImage.tiff */,
);
path = TestImages;
sourceTree = "<group>";
@@ -361,10 +389,17 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 7865C5E12941326F0010E17F /* bmpImage.bmp in Resources */,
+ 7865C5E4294132D50010E17F /* svgImage.svg in Resources */,
86430DF9272D71E9002D9D6C /* gifImage.gif in Resources */,
+ 7865C5FF294252A60010E17F /* proRawImage.dng in Resources */,
+ 7865C5EA294137960010E17F /* icoImage.ico in Resources */,
+ 7865C5E72941374F0010E17F /* heicImage.heic in Resources */,
86E9A894272754A30017E6E0 /* webpImage.webp in Resources */,
86E9A895272769130017E6E0 /* pngImage.png in Resources */,
+ 7865C5FC294157BC0010E17F /* icnsImage.icns in Resources */,
86E9A896272769150017E6E0 /* jpgImage.jpg in Resources */,
+ 7865C5ED294137AB0010E17F /* tiffImage.tiff in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -373,8 +408,15 @@
buildActionMask = 2147483647;
files = (
9FC8F0EC229FA68500C8D58F /* gifImage.gif in Resources */,
+ 7865C5EE294137AB0010E17F /* tiffImage.tiff in Resources */,
+ 7865C5E82941374F0010E17F /* heicImage.heic in Resources */,
+ 7865C5FD294157BC0010E17F /* icnsImage.icns in Resources */,
680049382280F2B9006DD6AB /* pngImage.png in Resources */,
680049392280F2B9006DD6AB /* jpgImage.jpg in Resources */,
+ 7865C5EB294137960010E17F /* icoImage.ico in Resources */,
+ 7865C5E22941326F0010E17F /* bmpImage.bmp in Resources */,
+ 7865C600294252A60010E17F /* proRawImage.dng in Resources */,
+ 7865C5E5294132D50010E17F /* svgImage.svg in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m
index e04c4f2..5594b9d 100644
--- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m
+++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m
@@ -19,8 +19,7 @@
NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"webpImage"
withExtension:@"webp"];
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
- PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
- withIdentifier:UTTypeWebP.identifier];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
[self verifySavingImageWithPickerResult:result fullMetadata:YES];
}
@@ -29,8 +28,7 @@
NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"pngImage"
withExtension:@"png"];
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
- PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
- withIdentifier:UTTypeWebP.identifier];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
[self verifySavingImageWithPickerResult:result fullMetadata:YES];
}
@@ -39,8 +37,7 @@
NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"jpgImage"
withExtension:@"jpg"];
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
- PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
- withIdentifier:UTTypeWebP.identifier];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
[self verifySavingImageWithPickerResult:result fullMetadata:YES];
}
@@ -49,20 +46,80 @@
NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"gifImage"
withExtension:@"gif"];
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
- PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
- withIdentifier:UTTypeWebP.identifier];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
[self verifySavingImageWithPickerResult:result fullMetadata:YES];
}
+- (void)testSaveBMPImage API_AVAILABLE(ios(14)) {
+ NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"bmpImage"
+ withExtension:@"bmp"];
+ NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
+
+ [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
+- (void)testSaveHEICImage API_AVAILABLE(ios(14)) {
+ NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"heicImage"
+ withExtension:@"heic"];
+ NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
+
+ [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
+- (void)testSaveICNSImage API_AVAILABLE(ios(14)) {
+ NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"icnsImage"
+ withExtension:@"icns"];
+ NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
+
+ [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
+- (void)testSaveICOImage API_AVAILABLE(ios(14)) {
+ NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"icoImage"
+ withExtension:@"ico"];
+ NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
+
+ [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
+- (void)testSaveProRAWImage API_AVAILABLE(ios(14)) {
+ NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"proRawImage"
+ withExtension:@"dng"];
+ NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
+
+ [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
+- (void)testSaveSVGImage API_AVAILABLE(ios(14)) {
+ NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"svgImage"
+ withExtension:@"svg"];
+ NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
+
+ [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
+- (void)testSaveTIFFImage API_AVAILABLE(ios(14)) {
+ NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"tiffImage"
+ withExtension:@"tiff"];
+ NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
+ [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
- (void)testSavePNGImageWithoutFullMetadata API_AVAILABLE(ios(14)) {
id photoAssetUtil = OCMClassMock([PHAsset class]);
NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"pngImage"
withExtension:@"png"];
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
- PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
- withIdentifier:UTTypeWebP.identifier];
+ PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
[self verifySavingImageWithPickerResult:result fullMetadata:NO];
OCMVerify(times(0), [photoAssetUtil fetchAssetsWithLocalIdentifiers:[OCMArg any]
@@ -76,11 +133,11 @@
* @param identifier local identifier of the asset
*/
- (PHPickerResult *)createPickerResultWithProvider:(NSItemProvider *)itemProvider
- withIdentifier:(NSString *)identifier API_AVAILABLE(ios(14)) {
+ API_AVAILABLE(ios(14)) {
PHPickerResult *result = OCMClassMock([PHPickerResult class]);
OCMStub([result itemProvider]).andReturn(itemProvider);
- OCMStub([result assetIdentifier]).andReturn(identifier);
+ OCMStub([result assetIdentifier]).andReturn(itemProvider.registeredTypeIdentifiers.firstObject);
return result;
}
diff --git a/packages/image_picker/image_picker_ios/example/ios/TestImages/bmpImage.bmp b/packages/image_picker/image_picker_ios/example/ios/TestImages/bmpImage.bmp
new file mode 100644
index 0000000..553e765
--- /dev/null
+++ b/packages/image_picker/image_picker_ios/example/ios/TestImages/bmpImage.bmp
Binary files differ
diff --git a/packages/image_picker/image_picker_ios/example/ios/TestImages/heicImage.heic b/packages/image_picker/image_picker_ios/example/ios/TestImages/heicImage.heic
new file mode 100644
index 0000000..03f41f6
--- /dev/null
+++ b/packages/image_picker/image_picker_ios/example/ios/TestImages/heicImage.heic
Binary files differ
diff --git a/packages/image_picker/image_picker_ios/example/ios/TestImages/icnsImage.icns b/packages/image_picker/image_picker_ios/example/ios/TestImages/icnsImage.icns
new file mode 100644
index 0000000..db0fbb0
--- /dev/null
+++ b/packages/image_picker/image_picker_ios/example/ios/TestImages/icnsImage.icns
Binary files differ
diff --git a/packages/image_picker/image_picker_ios/example/ios/TestImages/icoImage.ico b/packages/image_picker/image_picker_ios/example/ios/TestImages/icoImage.ico
new file mode 100644
index 0000000..30923c7
--- /dev/null
+++ b/packages/image_picker/image_picker_ios/example/ios/TestImages/icoImage.ico
Binary files differ
diff --git a/packages/image_picker/image_picker_ios/example/ios/TestImages/proRawImage.dng b/packages/image_picker/image_picker_ios/example/ios/TestImages/proRawImage.dng
new file mode 100644
index 0000000..7c3de76
--- /dev/null
+++ b/packages/image_picker/image_picker_ios/example/ios/TestImages/proRawImage.dng
Binary files differ
diff --git a/packages/image_picker/image_picker_ios/example/ios/TestImages/svgImage.svg b/packages/image_picker/image_picker_ios/example/ios/TestImages/svgImage.svg
new file mode 100644
index 0000000..19d6af9
--- /dev/null
+++ b/packages/image_picker/image_picker_ios/example/ios/TestImages/svgImage.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="12" height="7" viewBox="0 0 12 7">
+ <rect width="12" height="7" fill="red" />
+</svg>
\ No newline at end of file
diff --git a/packages/image_picker/image_picker_ios/example/ios/TestImages/tiffImage.tiff b/packages/image_picker/image_picker_ios/example/ios/TestImages/tiffImage.tiff
new file mode 100644
index 0000000..2431333
--- /dev/null
+++ b/packages/image_picker/image_picker_ios/example/ios/TestImages/tiffImage.tiff
Binary files differ
diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
index 7c8fbc9..16c2050 100644
--- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
+++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
@@ -6,6 +6,8 @@
#import "FLTPHPickerSaveImageToPathOperation.h"
+#import <os/log.h>
+
API_AVAILABLE(ios(14))
@interface FLTPHPickerSaveImageToPathOperation ()
@@ -88,25 +90,23 @@
if (@available(iOS 14, *)) {
[self setExecuting:YES];
- if ([self.result.itemProvider hasItemConformingToTypeIdentifier:UTTypeWebP.identifier]) {
+ // This supports uniform types that conform to UTTypeImage.
+ // This includes UTTypeHEIC, UTTypeHEIF, UTTypeLivePhoto, UTTypeICO, UTTypeICNS, UTTypePNG
+ // UTTypeGIF, UTTypeJPEG, UTTypeWebP, UTTypeTIFF, UTTypeBMP, UTTypeSVG, UTTypeRAWImage
+ if ([self.result.itemProvider hasItemConformingToTypeIdentifier:UTTypeImage.identifier]) {
[self.result.itemProvider
- loadDataRepresentationForTypeIdentifier:UTTypeWebP.identifier
+ loadDataRepresentationForTypeIdentifier:UTTypeImage.identifier
completionHandler:^(NSData *_Nullable data,
NSError *_Nullable error) {
- UIImage *image = [[UIImage alloc] initWithData:data];
- [self processImage:image];
+ if (data != nil) {
+ UIImage *image = [[UIImage alloc] initWithData:data];
+ [self processImage:image];
+ } else {
+ os_log_error(OS_LOG_DEFAULT, "Could not process image: %@",
+ error);
+ }
}];
- return;
}
-
- [self.result.itemProvider
- loadObjectOfClass:[UIImage class]
- completionHandler:^(__kindof id<NSItemProviderReading> _Nullable image,
- NSError *_Nullable error) {
- if ([image isKindOfClass:[UIImage class]]) {
- [self processImage:image];
- }
- }];
} else {
[self setFinished:YES];
}
diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml
index 6c78b23..e1b3891 100755
--- a/packages/image_picker/image_picker_ios/pubspec.yaml
+++ b/packages/image_picker/image_picker_ios/pubspec.yaml
@@ -2,7 +2,7 @@
description: iOS implementation of the image_picker plugin.
repository: https://github.com/flutter/plugins/tree/main/packages/image_picker/image_picker_ios
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
-version: 0.8.6+1
+version: 0.8.6+2
environment:
sdk: ">=2.14.0 <3.0.0"