【问题标题】:How to merge two UIImages?如何合并两个 UIImage?
【发布时间】:2015-11-07 11:27:41
【问题描述】:

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

这是一张 PNG 图片,我想将这张图片与我从手机中获取的另一张图片 (B) 合并,以创建类似这样的图片:

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

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

【问题讨论】:

    标签: ios swift uiimage core-graphics


    【解决方案1】:

    希望对你有帮助,

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

    一切顺利:)

    【讨论】:

    • 您可以尝试将 alpha 值更改为 1.0 或 0.1.. 不确定该值
    • 您可以使用不同版本的drawInRect,它不采用混合选项作为参数,即topImage!.drawInRect(CGRectMake(xPosition, yPosition, topImage!.size.width, topImage!.size.height))
    • 只有一件事,图像 (A) 是正方形,而我拍摄的图像是 16:9,我该如何解决?如果我使用您的功能,我拍摄的图像(B)会被拉伸!
    • 我使用了这个并生成了一个新图像的base64字符串。并导致空白图像。我在codebeautify.org/base64-to-image-converter# 上检查了它。图像会产生空白的白色图像。我想要做的是合并两个相互平行的图像。有人可以帮帮我吗?
    【解决方案2】:

    这样叠加的图片会干净很多:

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

    【讨论】:

    • 问题:当UIImageViewFrame(10,10, width, height) 时,我得到了顶部和底部的空间解决方案:将UIImageView 添加到视图中,使其变为Frame(0, 0, width, height) 并修复顶部和底部的空白空间底部。
    【解决方案3】:

    此解决方案的 Objective 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;
    }
    

    【讨论】:

    • 谁对我的答案投了反对票,您能否也花点时间添加您的评论为什么它被否决,这样我也会知道我的答案有什么问题。
    【解决方案4】:

    Swift 4 UIImage 扩展,可轻松实现图像合并/叠加。

    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
      }
    
    }
    

    【讨论】:

    • 谢谢这是一个不错的选择,但它不能正确处理负 posX 或 posY。我将添加一个将它们考虑在内的答案。
    【解决方案5】:

    投票的答案拉伸背景图片改变了它的比例。下面的解决方案通过从包含两个图像视图作为子视图的 UIView 渲染图像来解决此问题。

    回答您正在寻找的(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
    }
    

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

    • 示例:我希望图像的宽度和高度为 612,因此我将视图框架的宽度和高度设置为 306) // 享受 :)

    【讨论】:

    • @luca-alberto,这是您的解决方案!
    【解决方案6】:

    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
        }
    }
    

    【讨论】:

      【解决方案7】:

      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
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多