Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Make a GIF from a list of UIImages
//
// GifBuilder.swift
// Landscape
//
// Created by Cameron Deardorff on 6/10/20.
// Copyright © 2020 Cameron Deardorff. All rights reserved.
//
import UIKit
import ImageIO
import MobileCoreServices
struct GifBuilder {
var frames: Int
var duration: Float
var fps: Float { return Float(frames) / duration }
private var url: URL
private var destination: CGImageDestination
init?(frames: Int, duration: Float, name: String) {
self.frames = frames
self.duration = duration
guard let documentsDirectoryURL = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
else { return nil }
let filename = "\(name.replacingOccurrences(of: " ", with: "-")).gif"
self.url = documentsDirectoryURL.appendingPathComponent(filename)
guard let cfUrl = self.url as CFURL?,
let destination = CGImageDestinationCreateWithURL(cfUrl, kUTTypeGIF, frames, nil)
else { return nil }
self.destination = destination
let fileProperties: CFDictionary = [
kCGImagePropertyGIFDictionary as String: [
kCGImagePropertyGIFLoopCount as String: 0,
kCGImagePropertyGIFHasGlobalColorMap as String: false]
] as CFDictionary
CGImageDestinationSetProperties(destination, fileProperties)
}
func add(image: UIImage) {
autoreleasepool {
let frameProperties: CFDictionary = [
kCGImagePropertyGIFDictionary as String: [
(kCGImagePropertyGIFDelayTime as String): 1.0 / fps, // spf
kCGImagePropertyGIFHasGlobalColorMap as String: false]
] as CFDictionary
guard let cg = image.cgImage else { return }
CGImageDestinationAddImage(destination, cg, frameProperties)
}
}
func cancel() {
autoreleasepool {
CGImageDestinationFinalize(destination)
try? FileManager.default.removeItem(at: url)
}
}
func finish() -> URL? {
guard CGImageDestinationFinalize(destination) else { return nil }
return url
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment