[image_picker] ios:  support GIF animation and the scaling (#1638)

diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md
index 455ef52..ae67398 100644
--- a/packages/image_picker/CHANGELOG.md
+++ b/packages/image_picker/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.0+10
+
+* iOS: support picking GIF from gallery.
+
 ## 0.6.0+9
 
 * Add missing template type parameter to `invokeMethod` calls.
diff --git a/packages/image_picker/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
index cbe546c..bb359cc 100644
--- a/packages/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
@@ -24,6 +24,9 @@
 		97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
 		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
 		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+		9FC8F0E9229FA49E00C8D58F /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; };
+		9FC8F0EC229FA68500C8D58F /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; };
+		9FC8F0EE229FB90B00C8D58F /* ImageUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FC8F0ED229FB90B00C8D58F /* ImageUtilTests.m */; };
 		F4F7A436CCA4BF276270A3AE /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC32F6993F4529982D9519F1 /* libPods-Runner.a */; };
 /* End PBXBuildFile section */
 
@@ -77,6 +80,8 @@
 		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		9FC8F0E8229FA49E00C8D58F /* gifImage.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = gifImage.gif; sourceTree = "<group>"; };
+		9FC8F0ED229FB90B00C8D58F /* ImageUtilTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImageUtilTests.m; sourceTree = "<group>"; };
 		EC32F6993F4529982D9519F1 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
@@ -105,6 +110,7 @@
 			isa = PBXGroup;
 			children = (
 				6800491B2280D368006DD6AB /* Info.plist */,
+				9FC8F0ED229FB90B00C8D58F /* ImageUtilTests.m */,
 				680049252280D736006DD6AB /* MetaDataUtilTests.m */,
 				68F4B463228B3AB500C25614 /* PhotoAssetUtilTests.m */,
 			);
@@ -114,6 +120,7 @@
 		680049282280E33D006DD6AB /* TestImages */ = {
 			isa = PBXGroup;
 			children = (
+				9FC8F0E8229FA49E00C8D58F /* gifImage.gif */,
 				680049362280F2B8006DD6AB /* jpgImage.jpg */,
 				680049352280F2B8006DD6AB /* pngImage.png */,
 			);
@@ -291,6 +298,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				680049272280D79A006DD6AB /* Assets.xcassets in Resources */,
+				9FC8F0EC229FA68500C8D58F /* gifImage.gif in Resources */,
 				680049382280F2B9006DD6AB /* pngImage.png in Resources */,
 				680049392280F2B9006DD6AB /* jpgImage.jpg in Resources */,
 			);
@@ -301,6 +309,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+				9FC8F0E9229FA49E00C8D58F /* gifImage.gif in Resources */,
 				9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
 				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
 				9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
@@ -382,6 +391,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				9FC8F0EE229FB90B00C8D58F /* ImageUtilTests.m in Sources */,
 				680049262280D736006DD6AB /* MetaDataUtilTests.m in Sources */,
 				68F4B464228B3AB500C25614 /* PhotoAssetUtilTests.m in Sources */,
 			);
diff --git a/packages/image_picker/example/ios/TestImages/gifImage.gif b/packages/image_picker/example/ios/TestImages/gifImage.gif
new file mode 100644
index 0000000..5f989fc
--- /dev/null
+++ b/packages/image_picker/example/ios/TestImages/gifImage.gif
Binary files differ
diff --git a/packages/image_picker/example/ios/image_picker_exampleTests/ImageUtilTests.m b/packages/image_picker/example/ios/image_picker_exampleTests/ImageUtilTests.m
new file mode 100644
index 0000000..b554f4d
--- /dev/null
+++ b/packages/image_picker/example/ios/image_picker_exampleTests/ImageUtilTests.m
@@ -0,0 +1,48 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <XCTest/XCTest.h>
+#import "FLTImagePickerImageUtil.h"
+
+@interface ImageUtilTests : XCTestCase
+
+@property(strong, nonatomic) NSBundle *testBundle;
+
+@end
+
+@implementation ImageUtilTests
+
+- (void)setUp {
+  self.testBundle = [NSBundle bundleForClass:self.class];
+}
+
+- (void)testScaledImage_ShouldBeScaled {
+  NSData *data = [NSData dataWithContentsOfFile:[self.testBundle pathForResource:@"jpgImage"
+                                                                          ofType:@"jpg"]];
+  UIImage *image = [UIImage imageWithData:data];
+  UIImage *newImage = [FLTImagePickerImageUtil scaledImage:image maxWidth:@3 maxHeight:@2];
+
+  XCTAssertEqual(newImage.size.width, 3);
+  XCTAssertEqual(newImage.size.height, 2);
+}
+
+- (void)testScaledGIFImage_ShouldBeScaled {
+  // gif image that frame size is 3 and the duration is 1 second.
+  NSData *data = [NSData dataWithContentsOfFile:[self.testBundle pathForResource:@"gifImage"
+                                                                          ofType:@"gif"]];
+  GIFInfo info = [FLTImagePickerImageUtil scaledGIFImage:data maxWidth:@3 maxHeight:@2];
+
+  NSArray<UIImage *> *images = info.images;
+  NSTimeInterval duration = info.interval;
+
+  XCTAssertEqual(images.count, 3);
+  XCTAssertEqual(duration, 1);
+
+  for (UIImage *newImage in images) {
+    XCTAssertEqual(newImage.size.width, 3);
+    XCTAssertEqual(newImage.size.height, 2);
+  }
+}
+
+@end
diff --git a/packages/image_picker/example/ios/image_picker_exampleTests/MetaDataUtilTests.m b/packages/image_picker/example/ios/image_picker_exampleTests/MetaDataUtilTests.m
index 351f3f2..bc2fa79 100644
--- a/packages/image_picker/example/ios/image_picker_exampleTests/MetaDataUtilTests.m
+++ b/packages/image_picker/example/ios/image_picker_exampleTests/MetaDataUtilTests.m
@@ -29,6 +29,12 @@
                                                                              ofType:@"png"]];
   XCTAssertEqual([FLTImagePickerMetaDataUtil getImageMIMETypeFromImageData:dataPNG],
                  FLTImagePickerMIMETypePNG);
+
+  // test gif
+  NSData *dataGIF = [NSData dataWithContentsOfFile:[self.testBundle pathForResource:@"gifImage"
+                                                                             ofType:@"gif"]];
+  XCTAssertEqual([FLTImagePickerMetaDataUtil getImageMIMETypeFromImageData:dataGIF],
+                 FLTImagePickerMIMETypeGIF);
 }
 
 - (void)testSuffixFromType {
@@ -40,6 +46,10 @@
   XCTAssertEqualObjects(
       [FLTImagePickerMetaDataUtil imageTypeSuffixFromType:FLTImagePickerMIMETypePNG], @".png");
 
+  // test gif
+  XCTAssertEqualObjects(
+      [FLTImagePickerMetaDataUtil imageTypeSuffixFromType:FLTImagePickerMIMETypeGIF], @".gif");
+
   // test other
   XCTAssertNil([FLTImagePickerMetaDataUtil imageTypeSuffixFromType:FLTImagePickerMIMETypeOther]);
 }
diff --git a/packages/image_picker/example/ios/image_picker_exampleTests/PhotoAssetUtilTests.m b/packages/image_picker/example/ios/image_picker_exampleTests/PhotoAssetUtilTests.m
index e0eaf21..f0ff04d 100644
--- a/packages/image_picker/example/ios/image_picker_exampleTests/PhotoAssetUtilTests.m
+++ b/packages/image_picker/example/ios/image_picker_exampleTests/PhotoAssetUtilTests.m
@@ -24,7 +24,9 @@
                                                                              ofType:@"jpg"]];
   UIImage *imageJPG = [UIImage imageWithData:dataJPG];
   NSString *savedPathJPG = [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:dataJPG
-                                                                                  image:imageJPG];
+                                                                                  image:imageJPG
+                                                                               maxWidth:nil
+                                                                              maxHeight:nil];
   XCTAssertNotNil(savedPathJPG);
   XCTAssertEqualObjects([savedPathJPG substringFromIndex:savedPathJPG.length - 4], @".jpg");
 
@@ -38,7 +40,9 @@
                                                                              ofType:@"png"]];
   UIImage *imagePNG = [UIImage imageWithData:dataPNG];
   NSString *savedPathPNG = [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:dataPNG
-                                                                                  image:imagePNG];
+                                                                                  image:imagePNG
+                                                                               maxWidth:nil
+                                                                              maxHeight:nil];
   XCTAssertNotNil(savedPathPNG);
   XCTAssertEqualObjects([savedPathPNG substringFromIndex:savedPathPNG.length - 4], @".png");
 
@@ -80,4 +84,57 @@
                         @"aNote");
 }
 
+- (void)testSaveImageWithOriginalImageData_ShouldSaveAsGifAnimation {
+  // test gif
+  NSData *dataGIF = [NSData dataWithContentsOfFile:[self.testBundle pathForResource:@"gifImage"
+                                                                             ofType:@"gif"]];
+  UIImage *imageGIF = [UIImage imageWithData:dataGIF];
+  CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)dataGIF, nil);
+
+  size_t numberOfFrames = CGImageSourceGetCount(imageSource);
+
+  NSNumber *nilSize = (NSNumber *)[NSNull null];
+  NSString *savedPathGIF = [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:dataGIF
+                                                                                  image:imageGIF
+                                                                               maxWidth:nilSize
+                                                                              maxHeight:nilSize];
+  XCTAssertNotNil(savedPathGIF);
+  XCTAssertEqualObjects([savedPathGIF substringFromIndex:savedPathGIF.length - 4], @".gif");
+
+  NSData *newDataGIF = [NSData dataWithContentsOfFile:savedPathGIF];
+
+  CGImageSourceRef newImageSource = CGImageSourceCreateWithData((CFDataRef)newDataGIF, nil);
+
+  size_t newNumberOfFrames = CGImageSourceGetCount(newImageSource);
+
+  XCTAssertEqual(numberOfFrames, newNumberOfFrames);
+}
+
+- (void)testSaveImageWithOriginalImageData_ShouldSaveAsScalledGifAnimation {
+  // test gif
+  NSData *dataGIF = [NSData dataWithContentsOfFile:[self.testBundle pathForResource:@"gifImage"
+                                                                             ofType:@"gif"]];
+  UIImage *imageGIF = [UIImage imageWithData:dataGIF];
+
+  CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)dataGIF, nil);
+
+  size_t numberOfFrames = CGImageSourceGetCount(imageSource);
+
+  NSString *savedPathGIF = [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:dataGIF
+                                                                                  image:imageGIF
+                                                                               maxWidth:@3
+                                                                              maxHeight:@2];
+  NSData *newDataGIF = [NSData dataWithContentsOfFile:savedPathGIF];
+  UIImage *newImage = [[UIImage alloc] initWithData:newDataGIF];
+
+  XCTAssertEqual(newImage.size.width, 3);
+  XCTAssertEqual(newImage.size.height, 2);
+
+  CGImageSourceRef newImageSource = CGImageSourceCreateWithData((CFDataRef)newDataGIF, nil);
+
+  size_t newNumberOfFrames = CGImageSourceGetCount(newImageSource);
+
+  XCTAssertEqual(numberOfFrames, newNumberOfFrames);
+}
+
 @end
diff --git a/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.h b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.h
new file mode 100644
index 0000000..d9abec8
--- /dev/null
+++ b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.h
@@ -0,0 +1,29 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef struct GIFInfo {
+  // frames of animation
+  NSArray<UIImage *> *images;
+  NSTimeInterval interval;
+} GIFInfo;
+
+@interface FLTImagePickerImageUtil : NSObject
+
++ (UIImage *)scaledImage:(UIImage *)image
+                maxWidth:(NSNumber *)maxWidth
+               maxHeight:(NSNumber *)maxHeight;
+
+// Resize all gif animation frames.
++ (GIFInfo)scaledGIFImage:(NSData *)data
+                 maxWidth:(NSNumber *)maxWidth
+                maxHeight:(NSNumber *)maxHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.m
new file mode 100644
index 0000000..cd4d1ad
--- /dev/null
+++ b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.m
@@ -0,0 +1,108 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "FLTImagePickerImageUtil.h"
+#import <MobileCoreServices/MobileCoreServices.h>
+
+@implementation FLTImagePickerImageUtil : NSObject
+
++ (UIImage *)scaledImage:(UIImage *)image
+                maxWidth:(NSNumber *)maxWidth
+               maxHeight:(NSNumber *)maxHeight {
+  double originalWidth = image.size.width;
+  double originalHeight = image.size.height;
+
+  bool hasMaxWidth = maxWidth != (id)[NSNull null];
+  bool hasMaxHeight = maxHeight != (id)[NSNull null];
+
+  double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth;
+  double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight;
+
+  bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth;
+  bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight;
+  bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight;
+
+  if (shouldDownscale) {
+    double downscaledWidth = floor((height / originalHeight) * originalWidth);
+    double downscaledHeight = floor((width / originalWidth) * originalHeight);
+
+    if (width < height) {
+      if (!hasMaxWidth) {
+        width = downscaledWidth;
+      } else {
+        height = downscaledHeight;
+      }
+    } else if (height < width) {
+      if (!hasMaxHeight) {
+        height = downscaledHeight;
+      } else {
+        width = downscaledWidth;
+      }
+    } else {
+      if (originalWidth < originalHeight) {
+        width = downscaledWidth;
+      } else if (originalHeight < originalWidth) {
+        height = downscaledHeight;
+      }
+    }
+  }
+
+  UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
+  [image drawInRect:CGRectMake(0, 0, width, height)];
+
+  UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
+  UIGraphicsEndImageContext();
+
+  return scaledImage;
+}
+
++ (GIFInfo)scaledGIFImage:(NSData *)data
+                 maxWidth:(NSNumber *)maxWidth
+                maxHeight:(NSNumber *)maxHeight {
+  NSMutableDictionary<NSString *, id> *options = [NSMutableDictionary dictionary];
+  options[(NSString *)kCGImageSourceShouldCache] = @(YES);
+  options[(NSString *)kCGImageSourceTypeIdentifierHint] = (NSString *)kUTTypeGIF;
+
+  CGImageSourceRef imageSource =
+      CGImageSourceCreateWithData((CFDataRef)data, (CFDictionaryRef)options);
+
+  size_t numberOfFrames = CGImageSourceGetCount(imageSource);
+  NSMutableArray<UIImage *> *images = [NSMutableArray arrayWithCapacity:numberOfFrames];
+
+  NSTimeInterval interval = 0.0;
+  for (size_t index = 0; index < numberOfFrames; index++) {
+    CGImageRef imageRef =
+        CGImageSourceCreateImageAtIndex(imageSource, index, (CFDictionaryRef)options);
+
+    NSDictionary *properties = (NSDictionary *)CFBridgingRelease(
+        CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL));
+    NSDictionary *gifProperties = properties[(NSString *)kCGImagePropertyGIFDictionary];
+
+    NSNumber *delay = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
+    if (!delay) {
+      delay = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
+    }
+
+    if (interval == 0.0) {
+      interval = [delay doubleValue];
+    }
+
+    UIImage *image = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];
+    image = [self scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
+
+    [images addObject:image];
+
+    CGImageRelease(imageRef);
+  }
+
+  CFRelease(imageSource);
+
+  GIFInfo info;
+  info.images = images;
+  info.interval = interval;
+
+  return info;
+}
+
+@end
diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h
index 93a1af7..bc12f46 100644
--- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h
+++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.h
@@ -10,6 +10,7 @@
 typedef enum : NSUInteger {
   FLTImagePickerMIMETypePNG,
   FLTImagePickerMIMETypeJPEG,
+  FLTImagePickerMIMETypeGIF,
   FLTImagePickerMIMETypeOther,
 } FLTImagePickerMIMEType;
 
diff --git a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m
index 8cb4e4a..5123dec 100644
--- a/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m
+++ b/packages/image_picker/ios/Classes/FLTImagePickerMetaDataUtil.m
@@ -7,6 +7,7 @@
 
 static const uint8_t kFirstByteJPEG = 0xFF;
 static const uint8_t kFirstBytePNG = 0x89;
+static const uint8_t kFirstByteGIF = 0x47;
 
 NSString *const kFLTImagePickerDefaultSuffix = @".jpg";
 const FLTImagePickerMIMEType kFLTImagePickerMIMETypeDefault = FLTImagePickerMIMETypeJPEG;
@@ -21,6 +22,8 @@
       return FLTImagePickerMIMETypeJPEG;
     case kFirstBytePNG:
       return FLTImagePickerMIMETypePNG;
+    case kFirstByteGIF:
+      return FLTImagePickerMIMETypeGIF;
   }
   return FLTImagePickerMIMETypeOther;
 }
@@ -31,6 +34,8 @@
       return @".jpg";
     case FLTImagePickerMIMETypePNG:
       return @".png";
+    case FLTImagePickerMIMETypeGIF:
+      return @".gif";
     default:
       return nil;
   }
diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h
index 52b78d4..c03f1d5 100644
--- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h
+++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h
@@ -5,6 +5,8 @@
 #import <Foundation/Foundation.h>
 #import <Photos/Photos.h>
 
+#import "FLTImagePickerImageUtil.h"
+
 NS_ASSUME_NONNULL_BEGIN
 
 @interface FLTImagePickerPhotoAssetUtil : NSObject
@@ -12,7 +14,11 @@
 + (PHAsset *)getAssetFromImagePickerInfo:(NSDictionary *)info;
 
 // Save image with correct meta data and extention copied from the original asset.
-+ (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image;
+// maxWidth and maxHeight are used only for GIF images.
++ (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData
+                                       image:(UIImage *)image
+                                    maxWidth:(nullable NSNumber *)maxWidth
+                                   maxHeight:(nullable NSNumber *)maxHeight;
 
 // Save image with correct meta data and extention copied from image picker result info.
 + (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image;
diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m
index e13436c..b5b0723 100644
--- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m
+++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m
@@ -3,8 +3,11 @@
 // found in the LICENSE file.
 
 #import "FLTImagePickerPhotoAssetUtil.h"
+#import "FLTImagePickerImageUtil.h"
 #import "FLTImagePickerMetaDataUtil.h"
 
+@import MobileCoreServices;
+
 @implementation FLTImagePickerPhotoAssetUtil
 
 + (PHAsset *)getAssetFromImagePickerInfo:(NSDictionary *)info {
@@ -17,7 +20,10 @@
   return result.firstObject;
 }
 
-+ (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image {
++ (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData
+                                       image:(UIImage *)image
+                                    maxWidth:(NSNumber *)maxWidth
+                                   maxHeight:(NSNumber *)maxHeight {
   NSString *suffix = kFLTImagePickerDefaultSuffix;
   FLTImagePickerMIMEType type = kFLTImagePickerMIMETypeDefault;
   NSDictionary *metaData = nil;
@@ -28,7 +34,15 @@
         [FLTImagePickerMetaDataUtil imageTypeSuffixFromType:type] ?: kFLTImagePickerDefaultSuffix;
     metaData = [FLTImagePickerMetaDataUtil getMetaDataFromImageData:originalImageData];
   }
-  return [self saveImageWithMetaData:metaData image:image suffix:suffix type:type];
+  if (type == FLTImagePickerMIMETypeGIF) {
+    GIFInfo gifInfo = [FLTImagePickerImageUtil scaledGIFImage:originalImageData
+                                                     maxWidth:maxWidth
+                                                    maxHeight:maxHeight];
+
+    return [self saveImageWithMetaData:metaData gifInfo:gifInfo suffix:suffix];
+  } else {
+    return [self saveImageWithMetaData:metaData image:image suffix:suffix type:type];
+  }
 }
 
 + (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIImage *)image {
@@ -40,6 +54,13 @@
 }
 
 + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData
+                            gifInfo:(GIFInfo)gifInfo
+                             suffix:(NSString *)suffix {
+  NSString *path = [self temporaryFilePath:suffix];
+  return [self saveImageWithMetaData:metaData gifInfo:gifInfo path:path];
+}
+
++ (NSString *)saveImageWithMetaData:(NSDictionary *)metaData
                               image:(UIImage *)image
                              suffix:(NSString *)suffix
                                type:(FLTImagePickerMIMEType)type {
@@ -57,11 +78,64 @@
     data = [FLTImagePickerMetaDataUtil updateMetaData:metaData toImage:data];
   }
 
+  return [self createFile:data suffix:suffix];
+}
+
++ (NSString *)saveImageWithMetaData:(NSDictionary *)metaData
+                            gifInfo:(GIFInfo)gifInfo
+                               path:(NSString *)path {
+  CGImageDestinationRef destination = CGImageDestinationCreateWithURL(
+      (CFURLRef)[NSURL fileURLWithPath:path], kUTTypeGIF, gifInfo.images.count, NULL);
+
+  NSDictionary *frameProperties = [NSDictionary
+      dictionaryWithObject:[NSDictionary
+                               dictionaryWithObject:[NSNumber numberWithFloat:gifInfo.interval]
+                                             forKey:(NSString *)kCGImagePropertyGIFDelayTime]
+                    forKey:(NSString *)kCGImagePropertyGIFDictionary];
+
+  NSMutableDictionary *gifMetaProperties = [NSMutableDictionary dictionaryWithDictionary:metaData];
+  NSMutableDictionary *gifProperties =
+      (NSMutableDictionary *)gifMetaProperties[(NSString *)kCGImagePropertyGIFDictionary];
+  if (gifMetaProperties == nil) {
+    gifProperties = [NSMutableDictionary dictionary];
+  }
+
+  gifProperties[(NSString *)kCGImagePropertyGIFLoopCount] = [NSNumber numberWithFloat:0];
+
+  CGImageDestinationSetProperties(destination, (CFDictionaryRef)gifMetaProperties);
+
+  CGImagePropertyOrientation orientation = (CGImagePropertyOrientation)[metaData[(
+      __bridge NSString *)kCGImagePropertyOrientation] integerValue];
+
+  for (NSInteger index = 0; index < gifInfo.images.count; index++) {
+    UIImage *image = (UIImage *)[gifInfo.images objectAtIndex:index];
+    UIImage *newImage = [UIImage
+        imageWithCGImage:[image CGImage]
+                   scale:1.0
+             orientation:
+                 [FLTImagePickerMetaDataUtil
+                     getNormalizedUIImageOrientationFromCGImagePropertyOrientation:orientation]];
+
+    CGImageDestinationAddImage(destination, newImage.CGImage, (CFDictionaryRef)frameProperties);
+  }
+
+  CGImageDestinationFinalize(destination);
+  CFRelease(destination);
+
+  return path;
+}
+
++ (NSString *)temporaryFilePath:(NSString *)suffix {
   NSString *fileExtension = [@"image_picker_%@" stringByAppendingString:suffix];
   NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString];
   NSString *tmpFile = [NSString stringWithFormat:fileExtension, guid];
   NSString *tmpDirectory = NSTemporaryDirectory();
   NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile];
+  return tmpPath;
+}
+
++ (NSString *)createFile:(NSData *)data suffix:(NSString *)suffix {
+  NSString *tmpPath = [self temporaryFilePath:suffix];
   if ([[NSFileManager defaultManager] createFileAtPath:tmpPath contents:data attributes:nil]) {
     return tmpPath;
   } else {
diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m
index d4d5d7b..741e41f 100644
--- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m
+++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m
@@ -9,6 +9,7 @@
 #import <Photos/Photos.h>
 #import <UIKit/UIKit.h>
 
+#import "FLTImagePickerImageUtil.h"
 #import "FLTImagePickerMetaDataUtil.h"
 #import "FLTImagePickerPhotoAssetUtil.h"
 
@@ -249,7 +250,7 @@
     NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"];
 
     if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
-      image = [self scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
+      image = [FLTImagePickerImageUtil scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
     }
 
     PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info];
@@ -263,7 +264,11 @@
                            options:nil
                      resultHandler:^(NSData *_Nullable imageData, NSString *_Nullable dataUTI,
                                      UIImageOrientation orientation, NSDictionary *_Nullable info) {
-                       [weakSelf saveImageWithOriginalImageData:imageData image:image];
+                       // maxWidth and maxHeight are used only for GIF images.
+                       [weakSelf saveImageWithOriginalImageData:imageData
+                                                          image:image
+                                                       maxWidth:maxWidth
+                                                      maxHeight:maxHeight];
                      }];
     }
   }
@@ -278,59 +283,15 @@
   _arguments = nil;
 }
 
-- (UIImage *)scaledImage:(UIImage *)image
-                maxWidth:(NSNumber *)maxWidth
-               maxHeight:(NSNumber *)maxHeight {
-  double originalWidth = image.size.width;
-  double originalHeight = image.size.height;
-
-  bool hasMaxWidth = maxWidth != (id)[NSNull null];
-  bool hasMaxHeight = maxHeight != (id)[NSNull null];
-
-  double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth;
-  double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight;
-
-  bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth;
-  bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight;
-  bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight;
-
-  if (shouldDownscale) {
-    double downscaledWidth = floor((height / originalHeight) * originalWidth);
-    double downscaledHeight = floor((width / originalWidth) * originalHeight);
-
-    if (width < height) {
-      if (!hasMaxWidth) {
-        width = downscaledWidth;
-      } else {
-        height = downscaledHeight;
-      }
-    } else if (height < width) {
-      if (!hasMaxHeight) {
-        height = downscaledHeight;
-      } else {
-        width = downscaledWidth;
-      }
-    } else {
-      if (originalWidth < originalHeight) {
-        width = downscaledWidth;
-      } else if (originalHeight < originalWidth) {
-        height = downscaledHeight;
-      }
-    }
-  }
-
-  UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
-  [image drawInRect:CGRectMake(0, 0, width, height)];
-
-  UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
-  UIGraphicsEndImageContext();
-
-  return scaledImage;
-}
-
-- (void)saveImageWithOriginalImageData:(NSData *)originalImageData image:(UIImage *)image {
+- (void)saveImageWithOriginalImageData:(NSData *)originalImageData
+                                 image:(UIImage *)image
+                              maxWidth:(NSNumber *)maxWidth
+                             maxHeight:(NSNumber *)maxHeight {
   NSString *savedPath =
-      [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:originalImageData image:image];
+      [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:originalImageData
+                                                             image:image
+                                                          maxWidth:maxWidth
+                                                         maxHeight:maxHeight];
   [self handleSavedPath:savedPath];
 }
 
diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml
index 9b75a8f..6cddfa1 100755
--- a/packages/image_picker/pubspec.yaml
+++ b/packages/image_picker/pubspec.yaml
@@ -5,7 +5,7 @@
   - Flutter Team <flutter-dev@googlegroups.com>
   - Rhodes Davis Jr. <rody.davis.jr@gmail.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker
-version: 0.6.0+9
+version: 0.6.0+10
 
 flutter:
   plugin: