arrays - CGImageDestinationAddImage 的意外行为取决于我在 Swift 中的 UIImage var
问题描述
我有一个函数可以生成带有 UIImages 数组的 gif。图像数组大小为 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。
如果我在 CGImageDestinationAddImage 中使用“照片”,则生成的 gif 是我所期望的,而不是我上次创建的,但是 CGImage 没有调整大小,因为我没有通过该函数传递它们。
CGImageDestinationAddImage(destination, photo.cgImage!, gifProperties as CFDictionary?)
作为一个实验,我将 smallPhoto 定义为“照片”,期望它复制我之前定义的内容,并将其与 CGImageDestinationAddImage 一起使用。相反,生成的 gif 来自我上次发送给函数 generateGIF 函数的 UIImages 数组。
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?)
解决方案
我需要使用 CGImageDestinationFinalize(destination) 来完成我的图像。
func generateGIF(照片: [UIImage], 文件名: 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
}
}
let finalized:Bool = CGImageDestinationFinalize(destination)
if finalized {
// do something with gif, i.e. save to photo albums or display
// in my case I save using path as a URL
}
// return finalized boolean value
return finalized
}
推荐阅读
- java - 如何实现 SpringRetry
- python - 从 Python 中的日志文件中提取特定的 JSON
- numpy - HDF5 到 CSV 转换期间的多个错误
- ajax - 如何将 formData 转换为 AJAX 表单中的字符串?
- javascript - 使用 Swift 在具有 JS 文件的 WKWebview 中单击按钮时捕获 URL 字符串到 iOS 应用程序中
- javascript - lineTo 和 stroke 的区别
- x86 - 禁用分页后操作系统在远跳转时重置
- javascript - 使用javascript将数组中的多个对象合并为一个基于一对的键值对
- c++ - 通过 DP 打印 mXn 矩阵从左上角到右下角的所有可能路径
- spring - Spring Vault Kubernetes Auth 不接受自定义挂载路径