繁体   English   中英

如何将 Gif 图像合并到 UIImageView 中并快速覆盖 UIImageView?

[英]How to combine a Gif Image into UIImageView with overlaying UIImageView in swift?

一个 gif 图像被加载到 UIImageView 中(通过使用这个扩展),另一个 UIImageView 被覆盖在它上面。 一切正常,但问题是当我通过下面的代码将两者结合起来时,它显示静止图像 (.jpg)。 我想结合两者,结合后它也应该是一个动画图像 (.gif)。

let bottomImage = gifPlayer.image
let topImage = UIImage

let size = CGSize(width: (bottomImage?.size.width)!, height: (bottomImage?.size.height)!)
        
UIGraphicsBeginImageContext(size)
        
let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
bottomImage!.draw(in: areaSize)

topImage!.draw(in: areaSize, blendMode: .normal, alpha: 0.8)
let newImage = UIGraphicsGetImageFromCurrentImageContext()

UIGraphicsEndImageContext()

请单击此处了解有关此问题的更多信息。

UIImageView中使用动画 GIF 时,它会变成UIImage数组。

我们可以设置该数组(例如):

imageView.animationImages = arrayOfImages
imageView.animationDuration = 1.0

或者,我们可以将.image属性设置为animatedImage这就是您使用的 GIF-Swift 代码的工作方式:

if let img = UIImage.gifImageWithName("funny") {
    bottomImageView.image = img
}

在这种情况下,图像还包含持续时间:

img.images?.duration

因此,要生成带有边框/叠加图像的新动画 GIF,您需要获取该图像数组并生成添加了边框的每个“帧”。

这是一个简单的例子......

这假设:

  • 你正在使用GIF-Swift
  • 你在 Storyboard 中添加了bottomImageViewtopImageView
  • 你在名为“funny.gif”的包中有一个 GIF(如果你的不同,请编辑代码)
  • 你在资产中有一个“border.png”(同样,根据需要编辑代码)

并且您有一个连接到@IBAction的按钮:

import UIKit
import ImageIO
import UniformTypeIdentifiers

class animImageViewController: UIViewController {

    @IBOutlet var bottomImageView: UIImageView!
    @IBOutlet var topImageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        if let img = UIImage.gifImageWithName("funny") {
            bottomImageView.image = img
        }
        
        if let img = UIImage(named: "border") {
            topImageView.image = img
        }
        
    }
    
    @IBAction func saveButtonTapped(_ sender: Any) {
        generateNewGif(from: bottomImageView, with: topImageView)
    }

    func generateNewGif(from animatedImageView: UIImageView, with overlayImageView: UIImageView) {
        
        var images: [UIImage]!
        var delayTime: Double!
        
        guard let overlayImage = overlayImageView.image else {
            print("Could not get top / overlay image!")
            return
        }
        
        if let imgs = animatedImageView.image?.images {
            // the image view is using .image = animatedImage
            // unwrap the duration
            if let dur = animatedImageView.image?.duration {
                images = imgs
                delayTime = dur / Double(images.count)
            } else {
                print("Image view is using an animatedImage, but could not get the duration!" )
                return
            }
        } else if let imgs = animatedImageView.animationImages {
            // the image view is using .animationImages
            images = imgs
            delayTime = animatedImageView.animationDuration / Double(images.count)
        } else {
            print("Could not get images array!")
            return
        }
        
        // we now have a valid [UIImage] array, and
        //  a valid inter-frame duration, and
        //  a valid "overlay" UIImage
    
        // generate unique file name
        let destinationFilename = String(NSUUID().uuidString + ".gif")
        
        // create empty file in temp folder to hold gif
        let destinationURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(destinationFilename)
        
        // metadata for gif file to describe it as an animated gif
        let fileDictionary = [kCGImagePropertyGIFDictionary : [kCGImagePropertyGIFLoopCount : 0]]
        
        // create the file and set the file properties
        guard let animatedGifFile = CGImageDestinationCreateWithURL(destinationURL as CFURL, UTType.gif.identifier as CFString, images.count, nil) else {
            print("error creating file")
            return
        }
        
        CGImageDestinationSetProperties(animatedGifFile, fileDictionary as CFDictionary)
        
        let frameDictionary = [kCGImagePropertyGIFDictionary : [kCGImagePropertyGIFDelayTime: delayTime]]
        
        // use original size of gif
        let sz: CGSize = images[0].size
        
        let renderer: UIGraphicsImageRenderer = UIGraphicsImageRenderer(size: sz)
        
        // loop through the images
        //  drawing the top/border image on top of each "frame" image with 80% alpha
        //  then writing the combined image to the gif file
        images.forEach { img in
            
            let combinedImage = renderer.image { ctx in
                img.draw(at: .zero)
                overlayImage.draw(in: CGRect(origin: .zero, size: sz), blendMode: .normal, alpha: 0.8)
            }
            
            guard let cgFrame = combinedImage.cgImage else {
                print("error creating cgImage")
                return
            }
            
            // add the combined image to the new animated gif
            CGImageDestinationAddImage(animatedGifFile, cgFrame, frameDictionary as CFDictionary)
            
        }
        
        // done writing
        CGImageDestinationFinalize(animatedGifFile)
        
        print("New GIF created at:")
        print(destinationURL)
        print()
        
        // do something with the newly created file...
        //  maybe move it to documents folder, or
        //  upload it somewhere, or
        //  save to photos library, etc
    }
    
}

笔记:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM