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

* Fix GIF files not animating if permission not given. Fix PNG files getting convert to JPG if permission not given

* updated changelog and pubspec, added a comment
diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md
index 04bb4df..b75e633 100644
--- a/packages/image_picker/image_picker_ios/CHANGELOG.md
+++ b/packages/image_picker/image_picker_ios/CHANGELOG.md
@@ -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
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 091755c..027e287 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
@@ -21,7 +21,7 @@
   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)) {
@@ -30,7 +30,7 @@
   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)) {
@@ -39,7 +39,7 @@
   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)) {
@@ -48,7 +48,39 @@
   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)) {
@@ -57,7 +89,7 @@
   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)) {
@@ -66,7 +98,7 @@
   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)) {
@@ -75,7 +107,7 @@
   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)) {
@@ -84,7 +116,7 @@
   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)) {
@@ -93,7 +125,7 @@
   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)) {
@@ -102,7 +134,7 @@
   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)) {
@@ -110,7 +142,7 @@
                                                              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)) {
@@ -176,7 +208,7 @@
   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);
 }
 
@@ -204,7 +236,8 @@
  * @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"];
@@ -217,6 +250,7 @@
              fullMetadata:fullMetadata
            savedPathBlock:^(NSString *savedPath, FlutterError *error) {
              XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:savedPath]);
+             XCTAssertEqualObjects([NSURL URLWithString:savedPath].pathExtension, extension);
              [pathExpectation fulfill];
            }];
   operation.completionBlock = ^{
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 11fedfb..efcbdbe 100644
--- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
+++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
@@ -98,8 +98,7 @@
                                 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"
@@ -122,7 +121,9 @@
 /**
  * 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.
@@ -172,10 +173,13 @@
     }
   } 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];
   }
 }
diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml
index 5bfb885..1f4e2af 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+6
+version: 0.8.6+7
 
 environment:
   sdk: ">=2.14.0 <3.0.0"