How to combine two UIImages while maintaining aspect ratio and size?

The code has been added to Github so you understand the real problem.


This is the hierarchy:

-- ViewController.View P [width: 375, height: 667] ---- UIImageView A [width: 375, height: 667] Name: imgBackground [A is holding an image of size(1287,1662)] ---- UIImageView B [width: 100, height: 100] Name: imgForeground [B is holding an image of size(2400,982)] 

I am trying to combine A with B, but the result is stretched.

This is the merge code:

 func mixImagesWith(frontImage:UIImage?, backgroundImage: UIImage?, atPoint point:CGPoint, ofSize signatureSize:CGSize) -> UIImage { let size = self.imgBackground.frame.size UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale) backgroundImage?.draw(in: CGRect.init(x: 0, y: 0, width: size.width, height: size.height)) frontImage?.draw(in: CGRect.init(x: point.x, y: point.y, width: signatureSize.width, height: signatureSize.height)) let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return newImage } 

Note:

Here is a screenshot to understand the problem:

enter image description here

What should I do to get the correct output of the merge function?

+5
source share
2 answers

There are two errors in your code:

  • You must also calculate the aspect for the image of the document so that it places it in the UIImageView . In mergeImages() replace:

     img.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) 

    with:

     img.draw(in: getAspectFitFrame(sizeImgView: size, sizeImage: img.size)) 
  • When calculating an aspect, you center the image horizontally / vertically if its width / height is less than the UIImageView width / height. But instead of comparing newWidth and newHeight , factors should be compared:

     if hfactor > vfactor { y = (sizeImgView.height - newHeight) / 2 } else { x = (sizeImgView.width - newWidth) / 2 } 
+2
source

Try using code that works for me, hope it works for you too,

 func addWaterMarkToImage(img:UIImage, sizeWaterMark:CGRect, waterMarkImage:UIImage, completion : ((UIImage)->())?){ handler = completion let img2:UIImage = waterMarkImage let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height) UIGraphicsBeginImageContext(img.size) img.draw(in: rect) let frameAspect:CGRect = getAspectFitFrame(sizeImgView: sizeWaterMark.size, sizeImage: waterMarkImage.size) let frameOrig:CGRect = CGRect(x: sizeWaterMark.origin.x+frameAspect.origin.x, y: sizeWaterMark.origin.y+frameAspect.origin.y, width: frameAspect.size.width, height: frameAspect.size.height) img2.draw(in: frameOrig, blendMode: .normal, alpha: 1) let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() if handler != nil { handler!(result!) } } //MARK - Get Aspect Fit frame of UIImage func getAspectFitFrame(sizeImgView:CGSize, sizeImage:CGSize) -> CGRect{ let imageSize:CGSize = sizeImage let viewSize:CGSize = sizeImgView let hfactor : CGFloat = imageSize.width/viewSize.width let vfactor : CGFloat = imageSize.height/viewSize.height let factor : CGFloat = max(hfactor, vfactor) // Divide the size by the greater of the vertical or horizontal shrinkage factor let newWidth : CGFloat = imageSize.width / factor let newHeight : CGFloat = imageSize.height / factor var x:CGFloat = 0.0 var y:CGFloat = 0.0 if newWidth > newHeight{ y = (sizeImgView.height - newHeight)/2 } if newHeight > newWidth{ x = (sizeImgView.width - newWidth)/2 } let newRect:CGRect = CGRect(x: x, y: y, width: newWidth, height: newHeight) return newRect } 
+2
source

All Articles