//
// UIImage+GIF.swift
// swiftPractise
//
// Created by 云君 on 2017/6/5.
// Copyright © 2017年 pilgrim. All rights reserved.
//
import Foundation
import UIKit
import ImageIO
extension UIImage {
class func animatedGIFWith(data: Data?) -> UIImage? {
if let data = data {
if let source = CGImageSourceCreateWithData(data as CFData, nil) {
let count = CGImageSourceGetCount(source)
var animatedImage: UIImage? = nil
if count <= 1 {
animatedImage = UIImage(data: data)
} else {
var images: [UIImage] = []
var duration: TimeInterval = 0.0
for i in 0..<count {
let image = CGImageSourceCreateImageAtIndex(source, i, nil)
if image == nil {
continue
}
duration = duration + frameDurationAt(index: i, source: source)
images.append(UIImage(cgImage: image!, scale: UIScreen.main.scale, orientation: .up))
}
if duration == 0 {
duration = (1.0 / 10.0) * Double(count)
}
animatedImage = UIImage.animatedImage(with: images, duration: duration)
}
return animatedImage
} else {
return nil
}
} else {
return nil
}
}
class func frameDurationAt(index: Int, source: CGImageSource) -> TimeInterval {
var frameDuration: TimeInterval = 0.1
if let cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil) {
let frameProperties = cfFrameProperties as NSDictionary
if let gifProperties = frameProperties[kCGImagePropertyGIFDictionary as String] as? NSDictionary {
if let delayTimeUnclampedProp = gifProperties[kCGImagePropertyGIFUnclampedDelayTime as String] as? NSNumber {
frameDuration = delayTimeUnclampedProp.doubleValue
} else {
if let delayTimeProp = gifProperties[kCGImagePropertyGIFDelayTime as String] as? NSNumber {
frameDuration = delayTimeProp.doubleValue
}
}
}
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
// a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
// for more information.
if frameDuration < 0.011 {
frameDuration = 0.100
}
return frameDuration
}
class func animatedGIF(name: String) -> UIImage? {
let scale = UIScreen.main.scale
if scale > 1.0 {
if let retinaPath = Bundle.main.path(forResource: name.appending("@2x"), ofType: "gif") {
var data: Data?
do {
data = try Data(contentsOf: URL(fileURLWithPath: retinaPath))
} catch {
print("从path获取图片data失败")
}
if let data = data {
if let image = UIImage.animatedGIFWith(data: data) {
return image
}
}
}
if let path = Bundle.main.path(forResource: name, ofType: "gif") {
var data: Data?
do {
data = try Data(contentsOf: URL(fileURLWithPath: path))
} catch {
print("从path获取图片data失败")
}
if let data = data {
if let image = UIImage.animatedGIFWith(data: data) {
return image
}
}
}
return UIImage(named: name)
} else {
if let path = Bundle.main.path(forResource: name, ofType: "gif") {
var data: Data?
do {
data = try Data(contentsOf: URL(fileURLWithPath: path))
} catch {
print("从path获取图片data失败")
}
if let data = data {
if let image = UIImage.animatedGIFWith(data: data) {
return image
}
}
}
return UIImage(named: name)
}
}
func animatedImageByScalingAndCroppingTo(size: CGSize) -> UIImage? {
if __CGSizeEqualToSize(self.size, size) || __CGSizeEqualToSize(size, .zero) {
return self
}
var scaledSize = size
var thumbnailPoint = CGPoint.zero
let widthFactor = size.width / self.size.width
let heightFactor = size.height / self.size.height
let scaleFactor = widthFactor > heightFactor ? widthFactor : heightFactor
scaledSize.width = self.size.width * scaleFactor
scaledSize.height = self.size.height * scaleFactor
if widthFactor > heightFactor {
thumbnailPoint.y = (size.height - scaledSize.height) * 0.5
} else if widthFactor < heightFactor {
thumbnailPoint.x = (size.width - scaledSize.width) * 0.5
}
var scaledImages: [UIImage] = []
if let images = self.images {
for image in images {
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
image.draw(in: CGRect(x: thumbnailPoint.x, y: thumbnailPoint.y, width: scaledSize.width, height: scaledSize.height))
if let newImage = UIGraphicsGetImageFromCurrentImageContext() {
scaledImages.append(newImage)
}
UIGraphicsEndImageContext()
}
return UIImage.animatedImage(with: scaledImages, duration: self.duration)
} else {
return nil
}
}
}