13

I am learning Swift and I am creating an app that uses a personal photo and puts another on top of it. I now have a hacky solution, to create a screenshot of the area and save it. I need to do this in Swift

@IBAction func saveImage(sender: AnyObject) {
    //Create the UIImage
    UIGraphicsBeginImageContext(imageView.frame.size)
    view.layer.renderInContext(UIGraphicsGetCurrentContext())
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    //Save it to the camera roll
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}

But, this was working and isn't anymore. But, this is also not the best solution.

So guys, how can I save an image to the camera roll from a personal image, with an image as overlay?

Help would be greatly appreciated!! Thanks!

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
mindfreek
  • 684
  • 4
  • 9
  • 17
  • possible duplicate of [blend two uiimages](http://stackoverflow.com/questions/1309757/blend-two-uiimages) – cnoon Mar 15 '15 at 17:14

4 Answers4

37

I would recommend reading through this thread. All your answers are there. Once you read through that article, the following code sample should help you composite the two images together properly.

func saveImage() {
    let bottomImage = UIImage(named: "bottom")!
    let topImage = UIImage(named: "top")!

    let newSize = CGSizeMake(100, 100) // set this to what you need
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)

    bottomImage.drawInRect(CGRect(origin: CGPointZero, size: newSize))
    topImage.drawInRect(CGRect(origin: CGPointZero, size: newSize))

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

Hopefully this gets you going in the right direction.

Community
  • 1
  • 1
cnoon
  • 16,575
  • 7
  • 58
  • 66
9

Apple advises against UIGraphicsBeginImageContext, so as long as your app does not support devices older than iOS 10, then use something like this:

private func drawLogoIn(_ image: UIImage, _ logo: UIImage, position: CGPoint) -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: image.size)
    return renderer.image { context in
        image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
        logo.draw(in: CGRect(origin: position, size: logo.size))
    }
}

Besides performance gains, you get full P3 range.

Xys
  • 8,486
  • 2
  • 38
  • 56
Adrian
  • 415
  • 4
  • 18
6

UPDATE FOR SWIFT 4

func saveImage() {
    let bottomImage = UIImage(named: "your bottom image name")!
    let topImage = UIImage(named: "your top image name")!            
    let newSize = CGSize(width: 100, height: 100)   // set this to what you need
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
    bottomImage.draw(in: CGRect(origin: CGPoint.zero, size: newSize))
    topImage.draw(in: CGRect(origin: CGPoint.zero, size: newSize))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

To use the image just refer to newImage

EXAMPLE HOW TO USE THE IMAGE:

@IBOutlet weak var imageButton: UIButton!
imageButton.setBackgroundImage(newImage), for: .normal) 

This is an edit of cnoon's answer but optimized for Swift 4.

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Carter Cobb
  • 790
  • 7
  • 13
3

Updated to Swift 3.0:

func saveImage() {
    let bottomImage = UIImage(named: "bottom")!
    let topImage = UIImage(named: "top")!

    let newSize = CGSizeMake(100, 100) // set this to what you need
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)

    bottomImage.draw(in: CGRect(origin: CGPointZero, size: newSize))//As drawInRect is deprecated
    topImage.draw(at: CGRect(origin: CGPointZero, size: newSize))//As drawInRect is deprecated

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}
codingFriend1
  • 6,487
  • 6
  • 45
  • 67
quin
  • 435
  • 6
  • 11