如何在保持位置,大小和宽高比的同时合并两个UIImages?

时间:2017-05-21 10:04:16

标签: ios swift uiimage

我正在尝试合并两个不同大小的Babel + JSX

UIImage的大小如下:UIImage A像素 1287 × 1662具有以下尺寸:UIImage B像素

<小时/> 我正在跟随200 × 200 s显示A和B.

UIImageView backgroundImageView 的大小:UIImageView 375 x 667 foregroundImageView 的大小为:UIImageView

用户可以将100 x 100移至foregroundImageView上方的任意位置。

<小时/> 这是合并代码:

backgroundImageView

这实际上是合并并给我我想要的东西。但它减少了合并图像的大小。正如您在let previewImage:UIImage? = mergeImages(img: imgBackground.image!, sizeWaterMark: CGRect.init(origin: imgForeground.frame.origin, size: CGSize.init(width: 100, height: 100)), waterMarkImage: imgForeground.image!) func mergeImages(img:UIImage, sizeWaterMark:CGRect, waterMarkImage:UIImage) -> UIImage { let size = self.imgBackground.frame.size UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale) img.draw(in: getAspectFitFrame(sizeImgView: size, sizeImage: img.size)) 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) waterMarkImage.draw(in: frameOrig, blendMode: .normal, alpha: 1) let result:UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return result } 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 hfactor > vfactor { y = (sizeImgView.height - newHeight) / 2 } else { x = (sizeImgView.width - newWidth) / 2 } let newRect:CGRect = CGRect(x: x, y: y, width: newWidth, height: newHeight) return newRect } 函数中看到的那一行。

mergeImages

我希望尺寸应该是原始的 let size = self.imgBackground.frame.size 尺寸。所以如果我把它改成这个,

UIImage A

合并后,这将改变B在A上的位置。

要进行测试,您可以从here下载并查看源代码。

我应该怎样做才能保持原始尺寸,同时在适当的宽高比下确定B的确切位置?

1 个答案:

答案 0 :(得分:1)

我将实用程序函数设置为静态(将它们移动到单独的文件中更好),以确保它们不使用ViewController实例属性和方法。

mergeImages我删除了:

let size = self.imgBackground.frame.size

并将size替换为img.size。它与您在问题中使用的self.imgBackground.image!.size相同。

由于源图像和目标图像大小相同,因此无需调整方面,我们只需替换:

img.draw(in: getAspectFitFrame(sizeImgView: size, sizeImage: img.size))

img.draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: img.size))

我还提取了方面因子计算来分离函数getFactor,使代码更精细,使getAspectFitFrame不仅返回CGRect,还返回方面因子(稍后会有用)。

所以实用功能现在看起来像:

static func mergeImages(img: UIImage, sizeWaterMark: CGRect, waterMarkImage: UIImage) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(img.size, false, UIScreen.main.scale)
    img.draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: img.size))
    let (frameAspect, _) = getAspectFitFrame(from: sizeWaterMark.size, to: waterMarkImage.size)
    let frameOrig = CGRect(x: sizeWaterMark.origin.x + frameAspect.origin.x, y: sizeWaterMark.origin.y + frameAspect.origin.y, width: frameAspect.size.width, height: frameAspect.size.height)
    waterMarkImage.draw(in: frameOrig, blendMode: .normal, alpha: 1)
    let result = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return result
}

static func getAspectFitFrame(from: CGSize, to: CGSize) -> (CGRect, CGFloat) {
    let (hfactor, vfactor, factor) = ViewController.getFactor(from: from, to: to)

    // Divide the size by the greater of the vertical or horizontal shrinkage factor
    let newWidth = to.width / factor
    let newHeight = to.height / factor

    var x: CGFloat = 0.0
    var y: CGFloat = 0.0

    if hfactor > vfactor {
        y = (from.height - newHeight) / 2
    } else {
        x = (from.width - newWidth) / 2
    }
    return (CGRect(x: x, y: y, width: newWidth, height: newHeight), factor)
}

static func getFactor(from: CGSize, to: CGSize) -> (CGFloat, CGFloat, CGFloat) {
    let hfactor = to.width / from.width
    let vfactor = to.height / from.height
    return (hfactor, vfactor, max(hfactor, vfactor))
}

您还需要另一个效用函数来计算缩放水印的原点和大小:

static func getScaledFrame(from: CGSize, to: CGSize, target: CGRect) -> CGRect {
    let (aspectFitFrame, factor) = ViewController.getAspectFitFrame(from: from, to: to)
    return CGRect(
            origin: CGPoint(
                    x: (target.origin.x - aspectFitFrame.origin.x) * factor,
                    y: (target.origin.y - aspectFitFrame.origin.y) * factor),
            size: CGSize(width: target.width * factor, height: target.height * factor)
    )
}

现在您已准备好渲染合并图像:

    let previewImage = ViewController.mergeImages(
            img: imgBackground.image!,
            sizeWaterMark: ViewController.getScaledFrame(from: imgBackground.frame.size, to: imgBackground.image!.size, target: imgForeground.frame),
            waterMarkImage: imgForeground.image!
    )