如何在保持纵横比和大小的同时合并两个 UIImage?
Posted
技术标签:
【中文标题】如何在保持纵横比和大小的同时合并两个 UIImage?【英文标题】:How to merge two UIImages while keeping the aspect ratio and size? 【发布时间】:2017-05-10 11:45:24 【问题描述】:代码添加到Github,让你了解真正的问题。
这是层次结构:
-- 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)]
我正在尝试将 A 与 B 合并,但结果被拉伸了。
这是合并代码:
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
注意:
.contentMode = .scaleAspectFit 代码有效,但结果被拉伸。 查看代码中的这一行,let size = self.imgBackground.frame.size
– 我需要更改它来解决问题。 Find the origin of subview with respect to UIImage size
这是理解问题的屏幕截图:
我应该怎么做才能得到合并函数的正确输出?
【问题讨论】:
【参考方案1】:您的代码中有两个错误:
您还应该计算文档图像的纵横比以使其适合UIImageView
。在mergeImages()
中替换:
img.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
与:
img.draw(in: getAspectFitFrame(sizeImgView: size, sizeImage: img.size))
在计算纵横比时,如果图像的宽度/高度小于UIImageView
宽度/高度,则将图像水平/垂直居中。但是,您应该比较因素,而不是比较 newWidth
和 newHeight
:
if hfactor > vfactor
y = (sizeImgView.height - newHeight) / 2
else
x = (sizeImgView.width - newWidth) / 2
【讨论】:
嗨,迈克尔,感谢您的回答。这有一个小问题。由于两个图像的大小不同。合并后,UIImage B
的原点更改存在明显差异。我应该怎么做才能获得原始图像大小的确切来源(即UIImage A
)?
@Hemang 我在不同的模拟器上进行了测试,使用您提供的源代码合并后,我没有看到任何原点更改。你能单独问一个问题吗?
谢谢,迈克尔,这是新的question。【参考方案2】:
试试下面的代码,它对我有用,希望它也对你有用,
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
【讨论】:
以上是关于如何在保持纵横比和大小的同时合并两个 UIImage?的主要内容,如果未能解决你的问题,请参考以下文章