ios 如何合并两个 UIImages?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32006128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:15:44  来源:igfitidea点击:

How to merge two UIImages?

iosswiftuiimagecore-graphics

提问by Luca Alberto

I am trying to merge two different images and create a new one. This is the way I would like to do: I have this image (A): polaroid

我正在尝试合并两个不同的图像并创建一个新图像。这是我想做的方式:我有这张图片(A):宝丽来

It's a PNG image and I would like to merge this one with another image (B) which I took from the phone to create something like this: polaroid merged

这是一张 PNG 图像,我想将此图像与我从手机中获取的另一张图像 (B) 合并以创建如下内容: 宝丽来合并

I need a function who merge A with B creating C. The size must remain from the A image and the image B should auto adapt the size to fit into the polaroid (A). Is it possible to do that? Thank for your help!

我需要一个将 A 与 B 合并创建 C 的函数。大小必须与 A 图像保持一致,图像 B 应自动调整大小以适应宝丽来 (A)。有可能这样做吗?感谢您的帮助!

UPDATEJust one thing, the image (A) is a square and the image i took is a 16:9, how can i fix that?? If i use your function the image (B) that i took become stretched!

更新只有一件事,图像 (A) 是一个正方形,而我拍摄的图像是 16:9,我该如何解决?如果我使用你的功能,我拍摄的图像(B)就会被拉伸!

回答by Pallavi Konda

Hope this may help you,

希望这可以帮助你,

var bottomImage = UIImage(named: "bottom.png")
var topImage = UIImage(named: "top.png")

var size = CGSize(width: 300, height: 300)
UIGraphicsBeginImageContext(size)

let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
bottomImage!.draw(in: areaSize)

topImage!.draw(in: areaSize, blendMode: .normal, alpha: 0.8)

var newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()

All the Best :)

祝一切顺利 :)

回答by Svitlana

This way the overlay picture will be much cleaner

这样叠加图片会更干净

class func mergeImages(imageView: UIImageView) -> UIImage {
 UIGraphicsBeginImageContextWithOptions(imageView.frame.size, false, 0.0) 
 imageView.superview!.layer.renderInContext(UIGraphicsGetCurrentContext()!)
 let image = UIGraphicsGetImageFromCurrentImageContext()
 UIGraphicsEndImageContext()

 return image 
}

enter image description here

在此处输入图片说明

回答by budidino

Swift 4UIImageextension that enables easy image merging / overlaying.

Swift 4UIImage扩展,可以轻松合并/覆盖图像。

extension UIImage { 

  func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
    let newWidth = size.width < posX + image.size.width ? posX + image.size.width : size.width
    let newHeight = size.height < posY + image.size.height ? posY + image.size.height : size.height
    let newSize = CGSize(width: newWidth, height: newHeight)

    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
    draw(in: CGRect(origin: CGPoint.zero, size: size))
    image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: image.size))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()

    return newImage
  }

}

回答by Glen

Swift 5: Extension for UIImage

Swift 5:扩展 UIImage

extension UIImage {
  func mergeWith(topImage: UIImage) -> UIImage {
    let bottomImage = self

    UIGraphicsBeginImageContext(size)

    let areaSize = CGRect(x: 0, y: 0, width: bottomImage.size.width, height: bottomImage.size.height)
    bottomImage.draw(in: areaSize)

    topImage.draw(in: areaSize, blendMode: .normal, alpha: 1.0)

    let mergedImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return mergedImage
  }
}

回答by FrankByte.com

Slightly modified version of answer by budidino. This implementation also handles negative posX and posY correctly.

budidino 对答案稍作修改。此实现还正确处理负 posX 和 posY。

extension UIImage {
    func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
        let newWidth = posX < 0 ? abs(posX) + max(self.size.width, image.size.width) :
            size.width < posX + image.size.width ? posX + image.size.width : size.width
        let newHeight = posY < 0 ? abs(posY) + max(size.height, image.size.height) :
            size.height < posY + image.size.height ? posY + image.size.height : size.height
        let newSize = CGSize(width: newWidth, height: newHeight)

        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        let originalPoint = CGPoint(x: posX < 0 ? abs(posX) : 0, y: posY < 0 ? abs(posY) : 0)
        self.draw(in: CGRect(origin: originalPoint, size: self.size))
        let overLayPoint = CGPoint(x: posX < 0 ? 0 : posX, y: posY < 0 ? 0 : posY)
        image.draw(in: CGRect(origin: overLayPoint, size: image.size))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return newImage
    }
}

回答by iLearner

Objective C version of this solution with top image re-centered logic :

此解决方案的目标 C 版本具有顶部图像重新居中逻辑:

-(UIImage *)getImageInclosedWithinAnotherImage
{
    float innerImageSize = 20;
    UIImage *finalImage;

    UIImage *outerImage = [UIImage imageNamed:@"OuterImage.png"];
    UIImage *innerImage = [UIImage imageNamed:@"InnerImage.png"];

    CGSize outerImageSize = CGSizeMake(40, 40); // Provide custom size or size of your actual image
    UIGraphicsBeginImageContext(outerImageSize);

    //calculate areaSize for re-centered inner image
    CGRect areSize = CGRectMake(((outerImageSize.width/2) - (innerImageSize/2)), ((outerImageSize.width/2) - (innerImageSize/2)), innerImageSize, innerImageSize);
    [outerImage drawInRect:CGRectMake(0, 0, outerImageSize.width, outerImageSize.height)];
    [innerImage drawInRect:areSize blendMode:kCGBlendModeNormal alpha:1.0];

    finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return finalImage;
}

回答by Milez

The upvoted answer stretchesthe background image changing its ratio. The solution below fixes that by rendering the image from a UIView that contains the two image views as subviews.

赞成的答案会拉伸背景图像,改变其比例。下面的解决方案通过从包含两个图像视图作为子视图的 UIView 渲染图像来解决这个问题。

ANSWER YOU ARE LOOKING FOR (Swift 4):

您正在寻找的答案(Swift 4):

func blendImages(_ img: UIImage,_ imgTwo: UIImage) -> Data? {
    let bottomImage = img
    let topImage = imgTwo

    let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: 306, height: 306))
    let imgView2 = UIImageView(frame: CGRect(x: 0, y: 0, width: 306, height: 306))

    // - Set Content mode to what you desire
    imgView.contentMode = .scaleAspectFill
    imgView2.contentMode = .scaleAspectFit

    // - Set Images
    imgView.image = bottomImage
    imgView2.image = topImage

    // - Create UIView
    let contentView = UIView(frame: CGRect(x: 0, y: 0, width: 306, height: 306))
    contentView.addSubview(imgView)
    contentView.addSubview(imgView2)

    // - Set Size
    let size = CGSize(width: 306, height: 306)

    // - Where the magic happens
    UIGraphicsBeginImageContextWithOptions(size, true, 0)

    contentView.drawHierarchy(in: contentView.bounds, afterScreenUpdates: true)

    guard let i = UIGraphicsGetImageFromCurrentImageContext(),
        let data = UIImageJPEGRepresentation(i, 1.0)
        else {return nil}

    UIGraphicsEndImageContext()

    return data
}

The returned image data doubles the size of the image, so set the size of the views at half the desired size.

返回的图像数据使图像的大小加倍,因此将视图的大小设置为所需大小的一半。

  • EXAMPLE: I wanted the width and height of the image to be 612, so I set the view frames width and height to 306)// Enjoy :)
  • 示例:我希望图像的宽度和高度为612,因此我将视图框架的宽度和高度设置为306)// 享受 :)