¿Cómo fusionar dos UIImages mientras se mantiene la relación de aspecto y el tamaño?

El código se agrega a Github para que pueda comprender el problema real.


Esta es la jerarquía:

-- 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)] 

Estoy tratando de fusionar A con B, pero el resultado se ha estirado.

Este es el código de combinación:

 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 } 

Nota:

  • .contentMode = .scaleAspectFit
  • El código funciona, pero el resultado se ha estirado.
  • Vea esta línea en el código, let size = self.imgBackground.frame.size – Necesito cambiar esto para solucionar el problema. Encuentre el origen de la subvista con respecto al tamaño de UIImage

Aquí está la captura de pantalla para comprender el problema:

introduzca la descripción de la imagen aquí

¿Qué debo hacer para get la salida adecuada de la function de fusión?

Tienes dos errores en tu código:

  1. También debe calcular el aspecto de la image del documento para que encaje en UIImageView . En mergeImages() replace:

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

    con:

     img.draw(in: getAspectFitFrame(sizeImgView: size, sizeImage: img.size)) 
  2. Al calcular el aspecto, centrará la image horizontal / verticalmente si su ancho / alto es menor que UIImageView ancho / alto. Pero en lugar de comparar newWidth y newHeight , debe comparar los factores:

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

Pruebe con el código que me funciona, espero que también funcione para usted,

 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 }