gpt4 book ai didi

ios - 如何在保持位置、大小和纵横比不变的情况下合并两个 UIImage?

转载 作者:行者123 更新时间:2023-11-28 06:19:30 26 4
gpt4 key购买 nike

我正在尝试合并两个不同大小的 UIImage

我的 UIImage A 大小如下:1287 × 1662 像素UIImage B 的大小如下:200 × 200 像素


我在以下 UIImageView 中显示 A 和 B。

UIImageView backgroundImageView 大小:375 x 667UIImageView foregroundImageView 的大小: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 的大小。所以如果我把它改成这样,

    let size = self.imgBackground.image!.size

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

如需测试,可到here下载查看源码.

我应该怎么做才能保持原始大小不变,同时以适当的纵横比在 A 上准确定位 B?

最佳答案

我将实用程序函数设为静态(最好将它们移动到单独的文件中)以确保它们没有使用 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!
)

关于ios - 如何在保持位置、大小和纵横比不变的情况下合并两个 UIImage?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44095532/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com