Convert Gif image to NSData
Asked Answered
I

5

12

I have a gif image in my photo album. When I use the UIImagePickerController to select that image, I need to convert the image to NSData for storing.

Earlier, I used

NSData *thumbData = UIImageJPEGRepresentation(thumbnail, 0.5);

but it will not work with gif images. thumbData will be nil.

  1. How can I get NSData from the gif image?

  2. How can I know that it is a gif image that needs special handing?

Instant answered 25/5, 2013 at 9:51 Comment(3)
Did you also use UIImagePNGRepresentation(thumbnail); ?Atlantic
have a look at this link. It may be helpful to you.Element
Have solved your problem ?Briannabrianne
C
11

The key here is to save the GIF file or URL download directly into a NSData instead of making it a UIImage. Bypassing UIImage will let the GIF file keep the animation.

Here is some code to convert a GIF file into NSData:

NSString *filePath = [[NSBundle mainBundle] pathForResource: @"gifFileName" ofType: @"gif"];

NSData *gifData = [NSData dataWithContentsOfFile: filePath];

But in all honesty, you should really consider not using GIF at all.

Confectionary answered 25/5, 2013 at 20:9 Comment(0)
H
4

Swift

Gif must not be in assets.

let path = Bundle.main.path(forResource: "loader", ofType: "gif")!
let data = try! Data(contentsOf: URL(fileURLWithPath: path))
return data
Huysmans answered 20/3, 2018 at 19:8 Comment(0)
T
2

https://github.com/mattt/AnimatedGIFImageSerialization

UIImage *image = ...;
NSData *data = [AnimatedGIFImageSerialization animatedGIFDataWithImage:image
                                                              duration:1.0
                                                             loopCount:1
                                                                 error:nil];
Tupi answered 11/4, 2017 at 1:52 Comment(0)
S
1

Code to coverting .GIF file can converted in NSdata -

NSString *pathForFile = [[NSBundle mainBundle] pathForResource: @"myGif" ofType: @"gif"];

NSData *dataOfGif = [NSData dataWithContentsOfFile: pathForFile];

NSLog(@"Data: %@", dataOfGif);
Schrimsher answered 25/5, 2013 at 13:0 Comment(0)
T
1
  1. Those who are looking for a swifty answer to this question, here's an extension of UIImage that does the job.
import UIKit
import MobileCoreServices

extension UIImage {
    func UIImageAnimatedGIFRepresentation(gifDuration: TimeInterval = 0.0, loopCount: Int = 0) throws -> Data {
        let images = self.images ?? [self]
        let frameCount = images.count
        let frameDuration: TimeInterval = gifDuration <= 0.0 ? self.duration / Double(frameCount) : gifDuration / Double(frameCount)
        let frameDelayCentiseconds = Int(lrint(frameDuration * 100))
        let frameProperties = [
            kCGImagePropertyGIFDictionary: [
                kCGImagePropertyGIFDelayTime: NSNumber(value: frameDelayCentiseconds)
            ]
        ]

        guard let mutableData = CFDataCreateMutable(nil, 0),
           let destination = CGImageDestinationCreateWithData(mutableData, kUTTypeGIF, frameCount, nil) else {
            throw NSError(domain: "AnimatedGIFSerializationErrorDomain",
                          code: -1,
                          userInfo: [NSLocalizedDescriptionKey: "Could not create destination with data."])
        }
        let imageProperties = [
            kCGImagePropertyGIFDictionary: [kCGImagePropertyGIFLoopCount: NSNumber(value: loopCount)]
        ] as CFDictionary
        CGImageDestinationSetProperties(destination, imageProperties)
        for image in images {
            if let cgimage = image.cgImage {
                CGImageDestinationAddImage(destination, cgimage, frameProperties as CFDictionary)
            }
        }

        let success = CGImageDestinationFinalize(destination)
        if !success {
            throw NSError(domain: "AnimatedGIFSerializationErrorDomain",
                          code: -2,
                          userInfo: [NSLocalizedDescriptionKey: "Could not finalize image destination"])
        }
        return mutableData as Data
    }
}
  1. While the above extension will do the job, handling gif from image picker is simpler, here's the implementation in UIImagePickerControllerDelegate function.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    let info = Dictionary(uniqueKeysWithValues: info.map {key, value in (key.rawValue, value)})
    if let url = info[UIImagePickerController.InfoKey.referenceURL.rawValue] as? URL, url.pathExtension.lowercased() == "gif" {
       picker.dismiss(animated: false, completion: nil)
       url.getGifImageDataFromAssetUrl(completion: { imageData in
           // Use imageData here.
       })
       return
    }
}

with using an extension function in URL

import UIKit
import Photos

extension URL {
    func getGifImageDataFromAssetUrl(completion: @escaping(_ imageData: Data?) -> Void) {
        let asset = PHAsset.fetchAssets(withALAssetURLs: [self], options: nil)
        if let image = asset.firstObject {
            PHImageManager.default().requestImageData(for: image, options: nil) { (imageData, _, _, _) in
                completion(imageData)
            }
        }
    }
}
Tribulation answered 4/3, 2021 at 12:57 Comment(4)
Gives too slow gif animation, i tried different combinations but does not work.Barrus
Did you make sure that the Data -> UIImage conversion is not clamping the delay time? According to a few sources, any frame with duration less than 0.05 will be clamped to 0.1Tribulation
how can i make sure of that ? can you please guide ? i played with "frameDelayCentiseconds" variable. but nothing, outcome is almost sameBarrus
Thks a lot ! This help me to update Gif data then convert to Gif data again.Waggon

© 2022 - 2024 — McMap. All rights reserved.