Last active
February 16, 2019 06:55
-
-
Save thechaudharysab/b4f9884dcff20c3b8aeb5b4c1fd1756e to your computer and use it in GitHub Desktop.
Swift file that let you add GIF images in UIImageView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// GIFSupport.swift | |
// | |
// Created by Chaudhry Talha on 2/13/19. | |
// Copyright © 2019 ibjects. All rights reserved. | |
// | |
import UIKit | |
import ImageIO | |
fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool { | |
switch (lhs, rhs) { | |
case let (l?, r?): | |
return l < r | |
case (nil, _?): | |
return true | |
default: | |
return false | |
} | |
} | |
class GIFSupport: NSObject { | |
} | |
extension UIImage { | |
public class func gifImageWithData(_ data: Data) -> UIImage? { | |
guard let source = CGImageSourceCreateWithData(data as CFData, nil) else { | |
print("image doesn't exist") | |
return nil | |
} | |
return UIImage.animatedImageWithSource(source) | |
} | |
public class func gifImageWithURL(_ gifUrl:String) -> UIImage? { | |
guard let bundleURL:URL = URL(string: gifUrl) | |
else { | |
print("image named \"\(gifUrl)\" doesn't exist") | |
return nil | |
} | |
guard let imageData = try? Data(contentsOf: bundleURL) else { | |
print("image named \"\(gifUrl)\" into NSData") | |
return nil | |
} | |
return gifImageWithData(imageData) | |
} | |
public class func gifImageWithName(_ name: String) -> UIImage? { | |
guard let bundleURL = Bundle.main | |
.url(forResource: name, withExtension: "gif") else { | |
print("SwiftGif: This image named \"\(name)\" does not exist") | |
return nil | |
} | |
guard let imageData = try? Data(contentsOf: bundleURL) else { | |
print("SwiftGif: Cannot turn image named \"\(name)\" into NSData") | |
return nil | |
} | |
return gifImageWithData(imageData) | |
} | |
class func delayForImageAtIndex(_ index: Int, source: CGImageSource!) -> Double { | |
var delay = 0.1 | |
let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil) | |
let gifProperties: CFDictionary = unsafeBitCast( | |
CFDictionaryGetValue(cfProperties, | |
Unmanaged.passUnretained(kCGImagePropertyGIFDictionary).toOpaque()), | |
to: CFDictionary.self) | |
var delayObject: AnyObject = unsafeBitCast( | |
CFDictionaryGetValue(gifProperties, | |
Unmanaged.passUnretained(kCGImagePropertyGIFUnclampedDelayTime).toOpaque()), | |
to: AnyObject.self) | |
if delayObject.doubleValue == 0 { | |
delayObject = unsafeBitCast(CFDictionaryGetValue(gifProperties, | |
Unmanaged.passUnretained(kCGImagePropertyGIFDelayTime).toOpaque()), to: AnyObject.self) | |
} | |
delay = delayObject as! Double | |
if delay < 0.1 { | |
delay = 0.1 | |
} | |
return delay | |
} | |
class func gcdForPair(_ a: Int?, _ b: Int?) -> Int { | |
var a = a | |
var b = b | |
if b == nil || a == nil { | |
if b != nil { | |
return b! | |
} else if a != nil { | |
return a! | |
} else { | |
return 0 | |
} | |
} | |
if a < b { | |
let c = a | |
a = b | |
b = c | |
} | |
var rest: Int | |
while true { | |
rest = a! % b! | |
if rest == 0 { | |
return b! | |
} else { | |
a = b | |
b = rest | |
} | |
} | |
} | |
class func gcdForArray(_ array: Array<Int>) -> Int { | |
if array.isEmpty { | |
return 1 | |
} | |
var gcd = array[0] | |
for val in array { | |
gcd = UIImage.gcdForPair(val, gcd) | |
} | |
return gcd | |
} | |
class func animatedImageWithSource(_ source: CGImageSource) -> UIImage? { | |
let count = CGImageSourceGetCount(source) | |
var images = [CGImage]() | |
var delays = [Int]() | |
for i in 0..<count { | |
if let image = CGImageSourceCreateImageAtIndex(source, i, nil) { | |
images.append(image) | |
} | |
let delaySeconds = UIImage.delayForImageAtIndex(Int(i), | |
source: source) | |
delays.append(Int(delaySeconds * 1000.0)) // Seconds to ms | |
} | |
let duration: Int = { | |
var sum = 0 | |
for val: Int in delays { | |
sum += val | |
} | |
return sum | |
}() | |
let gcd = gcdForArray(delays) | |
var frames = [UIImage]() | |
var frame: UIImage | |
var frameCount: Int | |
for i in 0..<count { | |
frame = UIImage(cgImage: images[Int(i)]) | |
frameCount = Int(delays[Int(i)] / gcd) | |
for _ in 0..<frameCount { | |
frames.append(frame) | |
} | |
} | |
let animation = UIImage.animatedImage(with: frames, | |
duration: Double(duration) / 1000.0) | |
return animation | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment