Currently I’m working on a project to create a GIF from some images. I used a method (generateGifFromImages) from GitHub that takes a CGImage structure, which allows you to set the frame delay for each image. But even with the frame delay set to 2 seconds per frame, the resulting GIFs seem to play much faster, typically around 0.5 seconds per frame.
Below method I used to convert images to gif.
public func generateGifFromImages(imagesArray: [CGImage], repeatCount: Int = 0, frameDelay: TimeInterval, targetSize: CGSize, destinationURL: URL, progressHandler: @escaping (Float) -> (), callback: @escaping (_ data: Data?, _ error: NSError?) -> ()) {
DispatchQueue.global(qos: .background).async {
if let imageDestination = CGImageDestinationCreateWithURL(destinationURL as CFURL, kUTTypeGIF, imagesArray.count, nil) {
let gifProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: repeatCount]]
// Calculate total progress steps
let totalSteps = imagesArray.count
var currentStep = 0
for image in imagesArray {
// Resize image while maintaining aspect ratio
guard let resizedImage = resize(image: image, targetSize: targetSize) else {
callback(nil, self.errorFromString("Couldn't resize image"))
return
}
let frameProperties: [String: Any] = [kCGImagePropertyGIFDelayTime as String: frameDelay]
// Add the resized image to the GIF
CGImageDestinationAddImage(imageDestination, resizedImage, frameProperties as CFDictionary )
// Update progress
currentStep += 1
let progress = Float(currentStep) / Float(totalSteps)
progressHandler(progress)
}
CGImageDestinationSetProperties(imageDestination, gifProperties as CFDictionary)
if CGImageDestinationFinalize(imageDestination) {
do {
let data = try Data(contentsOf: destinationURL)
callback(data, nil)
} catch {
callback(nil, error as NSError)
}
} else {
callback(nil, self.errorFromString("Couldn't create the final image"))
}
}
}
}
I tried setting the frame delay to 2 seconds for each image using the kCGImagePropertyGIFDelayTime property, but the resulting GIF plays very fast. I have six images in the array, and I want at least a 1-second delay when each frame is played. Can someone help me please how to adjust the frame delay for each image so that the resulting GIF plays in slow motion, showing each frame for at least 1 second? Thank you in advance for your support!
The problem is the following line.
let frameProperties: [String: Any] = [kCGImagePropertyGIFDelayTime as String: frameDelay]
, which is [String : Double]
.
You are supposed to set it as [String : [String : Double]]
. So it should be
let frameProperties = [(kCGImagePropertyGIFDictionary as String): [(kCGImagePropertyGIFDelayTime as String): frameDelay]]
.