5
votes

In iOS Swift I'm having difficulty loading an animated GIF from the device photo library to a UIImageView or creating a .gif file from it. I have no problem displaying the animated GIF if it's a file on a server or if it's right in the app. However, when I load it from the photo library, I lose the animation. I found some Objective-C solutions and tried to convert them over to Swift, but haven't had any luck.

Here is what I have so far:

@IBAction func buttonTapped(sender: UIButton) {
    selectPhoto()
}

func selectPhoto() {
    let photoLibraryController = UIImagePickerController()
    photoLibraryController.delegate = self
    photoLibraryController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary

    let mediaTypes:[String] = [kUTTypeImage as String]
    photoLibraryController.mediaTypes = mediaTypes
    photoLibraryController.allowsEditing = false

    self.presentViewController(photoLibraryController, animated: true, completion: nil)
}

// UIImagePickerControllerDelegate
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    let origImage = info[UIImagePickerControllerOriginalImage] as! UIImage

    self.imageView.image = origImage

    picker.dismissViewControllerAnimated(true, completion: nil)

}

Optimally, I would like to save the photo library image to a gif file on the server. From there I have no trouble displaying it. However, I need some help getting the data from the photo library into some type of property, without losing the animation. Do I need to use something like ALAssetsLibrary for this?

Thanks.

2
Here's an approach--> github.com/kaishin/Gifu. Easiest way would be to use CocoaPods to install it. Here's how to use CocoaPods--> raywenderlich.com/97014/use-cocoapods-with-swift. Here's another solution in ObjC--> stackoverflow.com/a/4386709/4475605Adrian
Thanks, @Adrian. I actually had setup Gifu and was trying it. It works fine, except that it expects the image to be compiled into the app. It doesn't provide any method to get the image from somewhere other than right in the app. Therefore, I haven't been able to get it to work with an image in the photo library.Lastmboy
One can read my blog post about a GIF loading library that handles memory usage and loading from disk here: modejong.com/blog/post6_new_animated_gif_decoder_for_avanimatorMoDJ
Do you know of any way to use the device's photo library as the source? I'm not having any problems with them as a file or as a project resource. I just can't get them from the library to the file, without doing it manually.Lastmboy

2 Answers

8
votes

Yes, Use ALAssetsLibrary → now called PHAsset.

You should get the NSData of the gif, not UIImage( because UIImage will only get the first frame.)

So basically you would do something like this:

One you get the asset

let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true // adjust the parameters as you wish    

PHImageManager.default().requestImageData(for: asset, options: requestOptions, resultHandler: { (imageData, UTI, _, _) in
    if let uti = UTI,let data = imageData ,
        // you can also use UTI to make sure it's a gif
       UTTypeConformsTo(uti as CFString, kUTTypeGIF) {
        // save data here
    }
})      

Resource: PHAsset

0
votes

You can get an access to the location of the image file using InfoKey .imageURL and retrieve Data from this url

    // UIImagePickerControllerDelegate
    
          func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
                            if let path = info[.imageURL] as? URL {
                                 if let data = try? Data(contentsOf: path) {
                                 self.imageView.image = UIImage(data: data)
                    
//Now you have Data of a file: so you can convert it to image or gif or send to server or start animation (e.g. Framework JellyGIF)
                                 self.imageView.startGif(with: .data(data))
                }
                    
                        picker.dismissViewControllerAnimated(true, completion: nil)
                    
                    }