Jason Stone Jason Stone -4 years ago 141
Swift Question

How to save a uiimageview on top of another uiimageview (swift3)

Right Now I have two image views. All the button does is save the photo with the red box over the blue box and it will save image2 in the blue box and image1 in the red box. I would like red box to be saved over the blue box in just the small bottom right section of the blue box. Just like a lower third you see on tv ]]

enter image description here
import UIKit

class ViewController: UIViewController {


var image1 = UIImage(named: "f.jpg")
var image2 = UIImage(named: "l.jpg")
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.




}
func saveImage(image1:UIImage, image2:UIImage) -> UIImage {

let size1 = image1.size
let size2 = image2.size

let origin = CGPoint(x: size1.width-size2.width, y: size1.height - size2.height)

UIGraphicsBeginImageContextWithOptions(size2, false, 0.0)

image1.draw(in: CGRect(origin: CGPoint.zero, size: size1))
image2.draw(in: CGRect(origin: origin, size: size2))

let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
@IBAction func d(_ sender: Any) {
UIImageWriteToSavedPhotosAlbum(saveImage(image1:image1!, image2:image2!), self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}
func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}

}}


Photo that is saved in photo library

Answer Source

The code you have in saveImage function should work - assuming that image1 is larger than image2, however, if image1 and image2 are the same sizes then you will only see the second image because the origin will become (0,0). So in other words, if image1 and image2 are both 300x300, then image2 draws over image1.

The IBAction method appears to be wired up correctly and I believe what you are missing is some logic to resize the second image. Use the code below to guide you, the math will likely change depending on what ratio of image1 to image2 you're looking for.

func cropImageIntoQuarterSquare(image: UIImage) -> UIImage? {
    let originalImageSize: CGSize = image.size
    let smallImageSize = CGSize(width: (originalImageSize.width / 4), height: (originalImageSize.height / 4))

    UIGraphicsBeginImageContext(smallImageSize)
    image.draw(at: CGPoint.zero)
    let imageResult = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageResult
}

If you incorporate the resizing code then your IBAction might look something like this:

@IBAction func save(_ sender: Any) {
    guard let croppedImage = cropImageIntoQuarterSquare(image: image2),
        let combinedImage = saveImage(image1: image1, image2: croppedImage) else {
            // handle the error
            return
    }

    UIImageWriteToSavedPhotosAlbum(combinedImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

func saveImage(image1: UIImage, image2: UIImage) -> UIImage? {
    let size1 = image1.size
    let size2 = image2.size
    let origin = CGPoint(x: size1.width - size2.width, y: size1.height - size2.height)

    UIGraphicsBeginImageContext(size1)
    image1.draw(in: CGRect(origin: CGPoint.zero, size: size1))
    image2.draw(in: CGRect(origin: origin, size: size2))
    let combinedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return combinedImage
}

func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        // we got back an error!
        let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    } else {
        let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    }
}

Edit: Forgot to give credit to @Peter Tao for some of the code he already provided - and the link from hackingwithswift.com he provided.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download