如何复制 UIImage?

How to copy an UIImage?

我有一个 UIImageView 和一个 UIImage。我想将这些图片的副本分配给两个变量。根据用户的操作,应该对图像进行操作。问题是,图像在每个变量中都是相同的。我猜,因为它们是通过引用传递的。

let image1 = imageView.image!
let image2 = imageView.image!

如何获得此图片的两个单独副本?

我想要实现的目标:只裁剪一张图片,另一张保持原样。

let imageLeft = googleImageView.image!
let imageRef = CGImageCreateCopy(googleImageView.image!.CGImage)
let imageRight = UIImage(CGImage: imageRef!, scale: googleImageView.image!.scale, orientation: googleImageView.image!.imageOrientation)

if translation.x < 0 {
    let scale = imageLeft.scale
    let newRect = CGRectMake(0, 0, (imageLeft.size.width + translation.x) * scale, imageLeft.size.height * scale)
    let imageRef = CGImageCreateWithImageInRect(imageLeft.CGImage, newRect)
    
    if let croppedImage = imageRef {
        googleImageView.image = UIImage(CGImage: croppedImage, scale: scale, orientation: imageLeft.imageOrientation)
    }
} 
print("left image: \(imageLeft) right image \(imageRight)")

上面的代码打印到控制台:

left image: <UIImage: 0x7fd020dca070>, {111, 167} 
right image <UIImage: 0x7fd020dda430>, {111, 167}
left image: <UIImage: 0x7fd020df9ba0>, {110, 167} 
right image <UIImage: 0x7fd020d45670>, {110, 167}

...等等。因此,两个图像都获得了新的尺寸。只有左图应该被裁剪。

正如@Aggressor 建议的那样,您可以通过以下方式从 imageView 复制图像:

let newCgIm = CGImageCreateCopy(imageView.image?.CGImage)
let newImage = UIImage(CGImage: newCgIm, scale: imageView.image!.scale, orientation: imageView.image!.imageOrientation)

Swift3自带的cgImage有新的复制功能,也兼容Swift4.所以你可以这样使用

guard let cgImage = imageView.image?.cgImage?.copy() else {
        return
    }
let newImage = UIImage(cgImage: cgImage,
                       scale: imageView.image!.scale,
                       orientation: imageView.image!.imageOrientation)

Swift 5 或更好的解决方案:

将此扩展程序添加到您的代码中

extension UIImage {
    func clone() -> UIImage? {
        guard let originalCgImage = self.cgImage, let newCgImage = originalCgImage.copy() else {
            return nil
        }

        return UIImage(cgImage: newCgImage, scale: self.scale, orientation: self.imageOrientation)
    }
}

然后克隆图像以获取新的图像对象而不是引用:

let image1 = imageView.image!
let image2 = image1().clone()

!请注意,克隆图像会增加内存消耗。