简体   繁体   English

将 UIView 渲染为 UIImage 时出现图像尺寸错误

[英]Image size error while rendering UIView to UIImage

I would like to convert two images into one image with custom design.我想通过自定义设计将两张图像转换为一张图像。 The expected image is a snapshot of my UICollectionViewCell, not a UIImage actually.预期的图像是我的 UICollectionViewCell 的快照,实际上不是 UIImage。 I copied the layout codes from my custom UICVCell.swift file and tried to render the view into UIImage, but the result image is what you can see below.我从自定义 UICVCell.swift 文件中复制了布局代码,并尝试将视图渲染为 UIImage,但结果图像如下所示。

I searched through a lot of questions in SOF, but most of it was about 'How you can render a UIView into a UIImage.'我在 SOF 中搜索了很多问题,但其中大部分是关于“如何将 UIView 渲染为 UIImage”。 I've tried drawing too, but had the same messed up result.我也尝试过绘图,但结果同样混乱。

Can anybody tell me what's the problem?谁能告诉我有什么问题? I would really appreciate your help, it's my first question in SOF.非常感谢您的帮助,这是我在 SOF 中的第一个问题。 I might cry in a minute or two, literally...我可能会在一两分钟内哭泣,从字面上看...

class ViewController: UIViewController { class 视图控制器:UIViewController {

private var imageView: UIImageView = {
    let iv = UIImageView()
    iv.contentMode = .scaleAspectFit
    iv.clipsToBounds = true

    return iv
}()

func createBubbleImage(images: [UIImage?]) -> UIImage? {
    switch images.count {
    case 1:
        return images[0]
    case 2:
        let newView = UIView(frame: .init(x: 0, y: 0, width: 300, height: 300))
        let size = newView.frame.width

        let iv0 = UIImageView(image: images[0])
        iv0.contentMode = .scaleAspectFit
        iv0.clipsToBounds = true

        let iv1 = UIImageView(image: images[1])
        iv1.contentMode = .scaleAspectFit
        iv1.clipsToBounds = true

        newView.addSubview(iv0)
        iv0.anchor(top: newView.topAnchor, left: newView.leftAnchor, paddingTop: size * 0.04, paddingLeft: size * 0.04, width: size * 0.56, height: size * 0.56)
        newView.addSubview(iv1)
        iv1.anchor(bottom: newView.bottomAnchor, right: newView.rightAnchor, paddingBottom: size * 0.04, paddingRight: size * 0.04, width: size * 0.56, height: size * 0.56)
        
        iv0.layer.cornerRadius = size * 0.28
        iv1.layer.cornerRadius = size * 0.28
        
        let renderer = UIGraphicsImageRenderer(bounds: newView.bounds)
        return renderer.image { ctx in
            newView.layer.render(in: ctx.cgContext)
        }
        
    default:
        return UIImage(named: "logo")
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    view.backgroundColor = .white
    
    view.addSubview(imageView)
    imageView.center(inView: view)
    imageView.setDimensions(width: 300, height: 300)

    imageView.image = createBubbleImage(images: [UIImage(named: "0"), UIImage(named: "1")])
}

} }

Expected Image Result Image预期图像结果图像

Do the following:请执行下列操作:

  1. Remove the code lines that have the anchor method.删除具有anchor方法的代码行。
  2. Initiate the iv0 and iv1 with UIImageView(frame: ...)使用UIImageView(frame: ...)启动iv0iv1
  3. Add iv0.image = images[0] and iv1.image = images[1]添加iv0.image = images[0]iv1.image = images[1]

I also increased the radius a little bit because in my test device the images were not completely circular.我还稍微增加了半径,因为在我的测试设备中,图像不是完全圆形的。

The code should look like this:代码应如下所示:

func createBubbleImage(images: [UIImage?]) -> UIImage? {
    switch images.count {
    case 1:
        return images[0]
    case 2:
        let newView = UIView(frame: .init(x: 0, y: 0, width: 300, height: 300))
        let size = newView.frame.width

        let iv0 = UIImageView(frame: .init(x: 0, y: 0, width: 200, height: 200))
        iv0.image = images[0]
        iv0.contentMode = .scaleAspectFit
        iv0.clipsToBounds = true

        let iv1 = UIImageView(frame: .init(x: 100, y: 100, width: 200, height: 200))
        iv1.image = images[1]
        iv1.contentMode = .scaleAspectFit
        iv1.clipsToBounds = true

        newView.addSubview(iv0)
        newView.addSubview(iv1)

        iv0.layer.cornerRadius = size * 0.35
        iv1.layer.cornerRadius = size * 0.35

        let renderer = UIGraphicsImageRenderer(bounds: newView.bounds)
        return renderer.image { ctx in
            newView.layer.render(in: ctx.cgContext)
        }

    default:
        return UIImage(named: "logo")
    }
}

With it, the result is the following:有了它,结果如下:

在此处输入图像描述

I had to take a screenshot from your "expected image", that's why the images look like zoomed in. You can play with the UIImageView(frame: ...) part to adjust the two images as you want (I didn't played enough to avoid that cut in the edges, but it is possible with the right measures).我必须从您的“预期图像”中截取屏幕截图,这就是图像看起来像放大的原因。您可以使用UIImageView(frame: ...)部分来根据需要调整两个图像(我没有玩足以避免边缘切割,但可以通过正确的措施)。

Remark: the x and y values in the UIImageView frame are the horizontal and vertical distances from the top-left corner of newView to the top-left corner of your UIImageView, respectively.注:UIImageView 帧中的xy值分别是从 newView 的左上角到newView的左上角的水平和垂直距离。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM