15

I have an UIImageView with an UIImage. I want to assign a copy of these picture to two variables. Based on what the user is doing the image should be manipulated. The problem is, the image is the same in each variables. I guess, because they are passed by reference.

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

How do I get two separate copies of this image?

What I want to achieve: Just crop the one image, keep the other like the original.

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)")

The code above prints to the console:

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

... and so on. So, BOTH images gets a new size. Only the left Image should get cropped.

Cristik
  • 30,989
  • 25
  • 91
  • 127
heikomania
  • 445
  • 6
  • 13

3 Answers3

15

As @Aggressor suggested you can copy your image from imageView this way:

let newCgIm = CGImageCreateCopy(imageView.image?.CGImage)
let newImage = UIImage(CGImage: newCgIm, scale: imageView.image!.scale, orientation: imageView.image!.imageOrientation)
Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
7

There is a new copy function of cgImage comes with Swift 3 and also compatible with Swift 4. So you can use in this way

guard let cgImage = imageView.image?.cgImage?.copy() else {
        return
    }
let newImage = UIImage(cgImage: cgImage,
                       scale: imageView.image!.scale,
                       orientation: imageView.image!.imageOrientation)
abdullahselek
  • 7,893
  • 3
  • 50
  • 40
1

Solution for Swift 5 or better:

Add this extension to your code

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)
    }
}

then clone the image to get a new image object and not a reference:

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

! Note that cloning the image increases the memory consumption.

Jochen Holzer
  • 1,598
  • 19
  • 25