2

I have 2 UIImages, image1 and image2. I wish to overlay image2 onto image1, the overlaid image2 should be in the center of image1 and the result should return a UIImage and not UIImageView.

With my code below, I am able to overlay square image (this is image2) over circle image (this is image1), but the square is getting placed on the bottom right. I want the square to be in the center of the circle.

How can I achieve that with UIImage?

Note:

  • I know overlaying images is easier in SwiftUI and centering the images would be easier with UIImageView, but in my app, I have a requirement to overlay one image on top of other in the center and return it as an UIImage
  • In my case, the base image or image1 will always be a circular image, image2 could be any image, but the size will be smaller than image1 and should always be placed in the center. Just to keep this sample code simple, I am using a square image.
  • If it matters, my current circle image is 2000x2000 pixels and square image is 1200x1200 pixels.

Code:

import SwiftUI

struct ContentViewA: View {
    @State private var displayImage: Image?
    
    var body: some View {
        VStack {
            if let displayImage = displayImage {
                displayImage
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 80.0, height: 80.0)
                    .padding(.leading, 5.0)
                    .contentShape(Circle())
            } else {
                Text("There is no image to display.")
            }
        }
        .onAppear {
            displayImage = self.getImage()
        }
    }
    
    func getImage() -> Image {
        let baseCircleSymbol = UIImage.init(named: "circle")?.withTintColor(UIColor(Color.yellow), renderingMode: .alwaysTemplate) ?? UIImage()
        let squareIcon = UIImage.init(named: "square")?.withTintColor(UIColor(Color.blue), renderingMode: .alwaysTemplate) ?? UIImage()
        let displayImage = baseCircleSymbol.overlayImage(imageToOverlay: squareIcon)
        return Image(uiImage: displayImage)
    }
}

extension UIImage {
    func overlayImage(imageToOverlay: UIImage) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        let actualArea = CGRect(x: 0, y: 0, width: size.width, height: size.height)

        let overlayImageArea = CGRect(x: size.width - imageToOverlay.size.width,
                                      y: size.height - imageToOverlay.size.height,
                                      width: 900, height: 900)
        
        self.draw(in: actualArea)
        imageToOverlay.draw(in: overlayImageArea)
        
        let overlayed = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return overlayed
    }
}

Screenshot:

enter image description here

1
  • what's problem using ZStack this ? that may help to identify Commented Mar 13 at 7:23

2 Answers 2

1

Here is the updated dynamic frame for the imageToOverlay with calculation of center position. Used same size for the overlay image.

let imageToOverlaySize = imageToOverlay.size
let overlayImageArea = CGRect(x: size.width/2 - imageToOverlaySize.width/2,
                              y: size.height/2 - imageToOverlaySize.height/2,
                              width: imageToOverlaySize.width, height: imageToOverlaySize.height)
    
Sign up to request clarification or add additional context in comments.

Comments

0

let overlaySize = imageToOverlay.size
let overlayOrigin = CGPoint(x: (size.width - overlaySize.width) / 2,
                                    y: (size.height - overlaySize.height) / 2)
let overlayImageArea = CGRect(origin: overlayOrigin, size: overlaySize)

Here, you can use overlayOrigin to get the center of the base image

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.