Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[image_picker] GIF files will animate without permissions. PNG and GIF files will retain their image type if missing permissions. #7084

Merged
merged 2 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/image_picker/image_picker_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 0.8.6+7

* Fixes issue where GIF file would not animate without `Photo Library Usage` permissions. Fixes issue where PNG and GIF files were converted to JPG, but only when they are do not have `Photo Library Usage` permissions.
* Updates minimum Flutter version to 3.0.

## 0.8.6+6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ - (void)testSaveWebPImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testSavePNGImage API_AVAILABLE(ios(14)) {
Expand All @@ -30,7 +30,7 @@ - (void)testSavePNGImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"png"];
}

- (void)testSaveJPGImage API_AVAILABLE(ios(14)) {
Expand All @@ -39,7 +39,7 @@ - (void)testSaveJPGImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testSaveGIFImage API_AVAILABLE(ios(14)) {
Expand All @@ -48,7 +48,39 @@ - (void)testSaveGIFImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
NSData *dataGIF = [NSData dataWithContentsOfURL:imageURL];
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)dataGIF, nil);
size_t numberOfFrames = CGImageSourceGetCount(imageSource);

XCTestExpectation *pathExpectation = [self expectationWithDescription:@"Path was created"];
XCTestExpectation *operationExpectation =
[self expectationWithDescription:@"Operation completed"];

FLTPHPickerSaveImageToPathOperation *operation = [[FLTPHPickerSaveImageToPathOperation alloc]
initWithResult:result
maxHeight:@100
maxWidth:@100
desiredImageQuality:@100
fullMetadata:NO
savedPathBlock:^(NSString *savedPath, FlutterError *error) {
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:savedPath]);

// Ensure gif is animated.
XCTAssertEqualObjects([NSURL URLWithString:savedPath].pathExtension, @"gif");
NSData *newDataGIF = [NSData dataWithContentsOfFile:savedPath];
CGImageSourceRef newImageSource =
CGImageSourceCreateWithData((__bridge CFDataRef)newDataGIF, nil);
size_t newNumberOfFrames = CGImageSourceGetCount(newImageSource);
XCTAssertEqual(numberOfFrames, newNumberOfFrames);
[pathExpectation fulfill];
}];
operation.completionBlock = ^{
[operationExpectation fulfill];
};

[operation start];
[self waitForExpectationsWithTimeout:30 handler:nil];
XCTAssertTrue(operation.isFinished);
}

- (void)testSaveBMPImage API_AVAILABLE(ios(14)) {
Expand All @@ -57,7 +89,7 @@ - (void)testSaveBMPImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testSaveHEICImage API_AVAILABLE(ios(14)) {
Expand All @@ -66,7 +98,7 @@ - (void)testSaveHEICImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testSaveICNSImage API_AVAILABLE(ios(14)) {
Expand All @@ -75,7 +107,7 @@ - (void)testSaveICNSImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testSaveICOImage API_AVAILABLE(ios(14)) {
Expand All @@ -84,7 +116,7 @@ - (void)testSaveICOImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testSaveProRAWImage API_AVAILABLE(ios(14)) {
Expand All @@ -93,7 +125,7 @@ - (void)testSaveProRAWImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testSaveSVGImage API_AVAILABLE(ios(14)) {
Expand All @@ -102,15 +134,15 @@ - (void)testSaveSVGImage API_AVAILABLE(ios(14)) {
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];

[self verifySavingImageWithPickerResult:result fullMetadata:YES];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (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];
[self verifySavingImageWithPickerResult:result fullMetadata:YES withExtension:@"jpg"];
}

- (void)testNonexistentImage API_AVAILABLE(ios(14)) {
Expand Down Expand Up @@ -176,7 +208,7 @@ - (void)testSavePNGImageWithoutFullMetadata API_AVAILABLE(ios(14)) {
PHPickerResult *result = [self createPickerResultWithProvider:itemProvider];
OCMReject([photoAssetUtil fetchAssetsWithLocalIdentifiers:OCMOCK_ANY options:OCMOCK_ANY]);

[self verifySavingImageWithPickerResult:result fullMetadata:NO];
[self verifySavingImageWithPickerResult:result fullMetadata:NO withExtension:@"png"];
OCMVerifyAll(photoAssetUtil);
}

Expand Down Expand Up @@ -204,7 +236,8 @@ - (PHPickerResult *)createPickerResultWithProvider:(NSItemProvider *)itemProvide
* @param result the picker result
*/
- (void)verifySavingImageWithPickerResult:(PHPickerResult *)result
fullMetadata:(BOOL)fullMetadata API_AVAILABLE(ios(14)) {
fullMetadata:(BOOL)fullMetadata
withExtension:(NSString *)extension API_AVAILABLE(ios(14)) {
XCTestExpectation *pathExpectation = [self expectationWithDescription:@"Path was created"];
XCTestExpectation *operationExpectation =
[self expectationWithDescription:@"Operation completed"];
Expand All @@ -217,6 +250,7 @@ - (void)verifySavingImageWithPickerResult:(PHPickerResult *)result
fullMetadata:fullMetadata
savedPathBlock:^(NSString *savedPath, FlutterError *error) {
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:savedPath]);
XCTAssertEqualObjects([NSURL URLWithString:savedPath].pathExtension, extension);
[pathExpectation fulfill];
}];
operation.completionBlock = ^{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ - (void)start {
completionHandler:^(NSData *_Nullable data,
NSError *_Nullable error) {
if (data != nil) {
UIImage *image = [[UIImage alloc] initWithData:data];
[self processImage:image];
[self processImage:data];
} else {
FlutterError *flutterError =
[FlutterError errorWithCode:@"invalid_image"
Expand All @@ -122,7 +121,9 @@ - (void)start {
/**
* Processes the image.
*/
- (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) {
- (void)processImage:(NSData *)pickerImageData API_AVAILABLE(ios(14)) {
UIImage *localImage = [[UIImage alloc] initWithData:pickerImageData];

PHAsset *originalAsset;
// Only if requested, fetch the full "PHAsset" metadata, which requires "Photo Library Usage"
// permissions.
Expand Down Expand Up @@ -172,10 +173,13 @@ - (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) {
}
} else {
// Image picked without an original asset (e.g. User pick image without permission)
// maxWidth and maxHeight are used only for GIF images.
NSString *savedPath =
[FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:nil
image:localImage
imageQuality:self.desiredImageQuality];
[FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:pickerImageData
image:localImage
maxWidth:self.maxWidth
maxHeight:self.maxHeight
imageQuality:self.desiredImageQuality];
[self completeOperationWithPath:savedPath error:nil];
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/image_picker/image_picker_ios/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: image_picker_ios
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+6
version: 0.8.6+7

environment:
sdk: ">=2.14.0 <3.0.0"
Expand Down