I have merge two images into one. I already implemented it with some help from the internet but it takes around 2,5s. I'm testing on the simulator so let's take it as a reference.

I currently use UIGraphicsBeingImageContext. Is there any faster way to achieve it?

extension UIImage {
    func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat, topImageSize: CGSize,
                     combinedImage: @escaping (UIImage) -> Void) {
        DispatchQueue.global(qos: .userInteractive).async {
            let newWidth = self.size.width < posX + image.size.width ? posX + image.size.width : self.size.width
            let newHeight = self.size.height < posY + image.size.height ? posY + image.size.height : self.size.height
            let newSize = CGSize(width: newWidth, height: newHeight)

            UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
            self.draw(in: CGRect(origin: CGPoint.zero, size: self.size))
            image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: topImageSize))
            let newImage = UIGraphicsGetImageFromCurrentImageContext()!

            DispatchQueue.main.async {
  • \$\begingroup\$ What is the size of the images you are using? \$\endgroup\$ – ielyamani Dec 9 '18 at 12:42
  • \$\begingroup\$ @Carpsen90 the base image is iPhone image so it is around 3000x4000 and the top image is smaller ~1000x500. I implemented downsampling from WWDC 2018 session 219 (Image and graphics best practices) but it only shrinks down a photo. I tested it on iPhone 7 and it took me ~0,25s so it is almost instantaneous but maybe there are some tricks to speed up this process? \$\endgroup\$ – mikro098 Dec 9 '18 at 14:00
  • \$\begingroup\$ And btw when I'm combining two photos I get a peak of memory use of about ~170 MB on iPhone 7. \$\endgroup\$ – mikro098 Dec 9 '18 at 15:28
  • \$\begingroup\$ I've found that this code is almost twice as fast if topImageSize has the same with/height ratio as the size of image. Needed clarification: Could these images have some transparency, could the alpha channel be different from 1.0? \$\endgroup\$ – ielyamani Dec 13 '18 at 1:07
  • \$\begingroup\$ @Carpsen90 yep, the top image is .png with transparent background but the base image is not - it is just image taken with iPhone camera \$\endgroup\$ – mikro098 Dec 13 '18 at 8:00

On a simulator with the original code, it takes about 1.52s on my machine.

Since the base image won't get resized (self.size is passed in self.draw(in:)), and its alpha channel is always 1, I could gain at least 200ms by using the following :

self.draw(at: CGPoint.zero, blendMode: .copy, alpha: 1)
  • \$\begingroup\$ thanks, cool trick. I managed to drop from 1.13s to 1.07s or even 0.98 on the simulator. Not a major improvement but a welcome one. \$\endgroup\$ – mikro098 Dec 25 '18 at 21:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.