我有一个生成带有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是我所期望的,而不是我上次创建的gif,但是CGImage不会调整大小,因为我没有通过该函数传递它们。

CGImageDestinationAddImage(destination, photo.cgImage!, gifProperties as CFDictionary?)


作为实验,我将smallPhoto定义为“照片”,希望它可以复制之前定义的内容,并将其与CGImageDestinationAddImage一起使用。取而代之的是,生成的gif是我从上次发送到函数generateGIF函数的UIImages数组中得到的。

let smallerPhoto = photo
CGImageDestinationAddImage(destination, smallerPhoto.cgImage!, gifProperties as CFDictionary?)


另外,我尝试直接将smallerPhoto定义为照片中的当前数组索引,并在CGImageDestinationAddImage中使用它。这给了我传递给generateGIF的正确图像集。但是,这跳过了调整CGImages的大小,这是我需要做的。

let smallerPhoto = photos[inc]
CGImageDestinationAddImage(destination, smallerPhoto.cgImage!, gifProperties as CFDictionary?)

最佳答案

我需要使用CGImageDestinationFinalize(destination)最终确定图像。

func generateGIF(照片:[UIImage],文件名:String)->布尔{

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


}

10-08 06:16
查看更多