У меня есть функция, которая генерирует GIF с массивом UIImages. Размер массива изображений составляет 31, но я установил емкость на 15, потому что я использую только избранные изображения.
В конечном счете, проблема, с которой я сталкиваюсь, заключается в том, что когда я использую функцию для изменения размера CGImage и использую ее в качестве изображения в CGImageDestinationAddImage, получаемый в результате gif представляет собой фотографии, которые я отправлял ранее, вместо фотографий, которые я на этот раз через функцию. Я понятия не имею, как это может произойти, поскольку полученный gif все еще может генерировать массив изображений, который я использовал ранее, даже если я закрылся из приложения.
Ниже приведены основные функции generateGIF и imageWithImage, а затем я покажу разные вещи, которые я пробовал. Полученные результаты.
func generateGIF(photos: [UIImage], filename: String) -> Bool {
let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let path = documentsDirectoryPath.appending(filename)
let fileProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]
var gifProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: 0.1]] // actual speed is 0.2
gifProperties = [kCGImagePropertyGIFDictionary as String: [kCGImageDestinationLossyCompressionQuality as String: 0.1]]
let cfURL = URL(fileURLWithPath: path) as CFURL
let imageCapacity = 15
if let destination = CGImageDestinationCreateWithURL(cfURL, kUTTypeGIF, imageCapacity, nil) {
CGImageDestinationSetProperties(destination, fileProperties as CFDictionary?)
var inc:Int = 0
for _ in 0..<imageCapacity { // actual photos.count is 31
// I create 'photo' to determine what new size I should
// use, for my own convenience, not included in this code
let photo = photos[inc]
let width:CGFloat = 200
let smallerPhoto = imageWithImage(image:photos[inc], newWidth:width)
CGImageDestinationAddImage(destination, smallerPhoto.cgImage!, gifProperties as CFDictionary?)
inc += 2
}
}
// do something with gif, i.e. save to photo albums or display
// in my case I save using path as a URL
}
func imageWithImage(image:UIImage, newWidth:CGFloat) -> UIImage{
let scale = newWidth / image.size.width
let newHeight = image.size.height * scale
let newSize = CGSize(width: newWidth, height: newHeight)
let renderer = UIGraphicsImageRenderer(size: newSize)
let image = renderer.image { (context) in
image.draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: newSize))
}
return image
}
Как я объяснил, полученный gif с использованием приведенного выше кода сделает gif из изображений, которые я сделал ранее.
Если я использую 'photo' в CGImageDestinationAddImage, получаемый в результате gif будет тем, что я ожидал, а не тем, что я создал в прошлый раз, но CGImages не изменяется, потому что я не пропустил их через эту функцию.
CGImageDestinationAddImage(destination, photo.cgImage!, gifProperties as CFDictionary?)
В качестве эксперимента я определил lowerPhoto как 'photo', ожидая, что он скопирует то, что я определил ранее, и использовал это с CGImageDestinationAddImage. Вместо этого полученный gif - это то, что я из массива UIImages, который я отправил в функцию generateGIF с последнего раза.
let smallerPhoto = photo
CGImageDestinationAddImage(destination, smallerPhoto.cgImage!, gifProperties as CFDictionary?)
В качестве альтернативы, я попытался определить smallPhoto непосредственно как текущий индекс массива на фотографиях и использовал его в CGImageDestinationAddImage. Это дало мне правильный набор изображений, которые я передал в generateGIF. Тем не менее, это пропускает изменение размера CGImages, что мне нужно сделать.
let smallerPhoto = photos[inc]
CGImageDestinationAddImage(destination, smallerPhoto.cgImage!, gifProperties as CFDictionary?)