【问题标题】:how to get one high quality image including subview image on scrollview如何获得一张高质量的图像,包括滚动视图上的子视图图像
【发布时间】:2020-03-17 05:21:30
【问题描述】:

我正在尝试图像裁剪教程

我想制作裁剪图像并添加贴纸的应用。

subviews 是 imageview 的子视图 ( imageview.addsubview(subview) )

please check this Image link

一切都很好,但我无法制作最终图像。 我想使用原始分辨率制作最终图像,但我的功能结果分辨率太低

我为此浪费了 5 天时间

示例)

scrollview 的 rect 0, 0, 200, 400

图像视图大小 7680 x 4320

我尝试了下面的代码。 但结果质量非常低。因为分辨率是 200x400(scrollview 的 rect)。

func screenshot() -> UIImage {
    guard let imageview = imageview else { return UIImage() }
    UIGraphicsBeginImageContextWithOptions(self.scrollView.bounds.size, false, UIScreen.main.scale)
    let offset = self.scrollView.contentOffset
    guard let thisContext = UIGraphicsGetCurrentContext() else { return UIImage() }
    thisContext.translateBy(x: -offset.x, y: -offset.y)
    self.scrollView.layer.render(in: thisContext)
    let visibleScrollViewImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return visibleScrollViewImage ?? UIImage()
}

请告诉我如何制作高质量分辨率的最终图像,包括贴纸子视图

如何使用

获得一张高质量的图像

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    使用该方法,您可以获得屏幕上呈现的图像。

    想要做的是计算“贴纸”的大小和相对于缩放图像的位置,然后组合图像。

    您可以使用此扩展程序将一张图片叠加在另一张图片上:

    extension UIImage {
        func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
            let rFormat = UIGraphicsImageRendererFormat()
            let renderer = UIGraphicsImageRenderer(size: size, format: rFormat)
            let newImage = renderer.image {
                (context) in
                self.draw(at: .zero)
                image.draw(at: CGPoint(x: posX, y: posY))
            }
            return newImage
        }
    }
    

    通过调用来使用它(例如):

    let combinedImage = bkgImage.overlayWith(image: stickerImage, posX: 1000.0, posY: 1000.0)
    

    上面写着“通过将贴纸图像覆盖到x: 1000, y:1000 的背景图像上来创建一个新的UIImage

    请记住,您需要转换您的坐标...因此,如果您在 200 x 400 滚动视图中显示您的 7680 x 4320 图像(此处不考虑任何缩放),屏幕上的图像大小将是711 x 400。如果用户将贴纸放在100, 50,则原始尺寸图像上的实际位置将是:

        let scaleFactor = bkgImage.size.height / 400.0
        let x = 100.0 * scaleFactor
        let y = 50.0 * scaleFactor
    
        // scaleFactor equals 10.8
        // x equals 100 * 10.8 == 1080
        // y equals 50 * 10.8 == 540
    
        let combinedImage = bkgImage.overlayWith(image: stickerImage, posX: x, posY: y)
    

    这是一个您可以试用的基本示例。

    它以5120 x 2880的背景图片开头:

    512 x 512 的“贴纸”图片:

    结果,贴纸位于x: 1000, y:1000。顶部图像是原始背景(aspectFit),中间图像是组合图像(同样,aspectFit),底部图像是滚动视图中实际大小的组合图像:

    使用此源代码运行该示例(所有代码,无 @IBoutlet):

    import UIKit
    
    extension UIImage {
        func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
            let rFormat = UIGraphicsImageRendererFormat()
            let renderer = UIGraphicsImageRenderer(size: size, format: rFormat)
            let newImage = renderer.image {
                (context) in
                self.draw(at: .zero)
                image.draw(at: CGPoint(x: posX, y: posY))
            }
            return newImage
        }
    }
    
    class ViewController: UIViewController {
    
        let origImageView: UIImageView = {
            let v = UIImageView()
            v.translatesAutoresizingMaskIntoConstraints = false
            v.contentMode = .scaleAspectFit
            v.backgroundColor = .yellow
            return v
        }()
    
        let modImageView: UIImageView = {
            let v = UIImageView()
            v.translatesAutoresizingMaskIntoConstraints = false
            v.contentMode = .scaleAspectFit
            v.backgroundColor = .yellow
            return v
        }()
    
        let actualSizeImageView: UIImageView = {
            let v = UIImageView()
            v.translatesAutoresizingMaskIntoConstraints = false
            v.contentMode = .topLeft
            v.backgroundColor = .yellow
            return v
        }()
    
        let scrollView: UIScrollView = {
            let v = UIScrollView()
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            guard let bkgImage = UIImage(named: "background"),
                let stickerImage = UIImage(named: "sticker") else {
    
                    fatalError("missing images")
    
            }
    
            view.backgroundColor = .systemGreen
    
            view.addSubview(origImageView)
            view.addSubview(modImageView)
    
            view.addSubview(scrollView)
            scrollView.addSubview(actualSizeImageView)
    
            let g = view.safeAreaLayoutGuide
    
            let sg = scrollView.contentLayoutGuide
    
            NSLayoutConstraint.activate([
    
                origImageView.topAnchor.constraint(equalTo: g.topAnchor, constant: 10.0),
                origImageView.centerXAnchor.constraint(equalTo: g.centerXAnchor, constant: 0.0),
                origImageView.widthAnchor.constraint(equalToConstant: 200.0),
                origImageView.heightAnchor.constraint(equalToConstant: 120.0),
    
                modImageView.topAnchor.constraint(equalTo: origImageView.bottomAnchor, constant: 10.0),
                modImageView.centerXAnchor.constraint(equalTo: origImageView.centerXAnchor, constant: 0.0),
                modImageView.widthAnchor.constraint(equalTo: origImageView.widthAnchor),
                modImageView.heightAnchor.constraint(equalTo: origImageView.heightAnchor),
    
                scrollView.topAnchor.constraint(equalTo: modImageView.bottomAnchor, constant: 10.0),
                scrollView.centerXAnchor.constraint(equalTo: origImageView.centerXAnchor, constant: 0.0),
                scrollView.widthAnchor.constraint(equalTo: g.widthAnchor, constant: -10.0),
                scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -10.0),
    
                actualSizeImageView.topAnchor.constraint(equalTo: sg.topAnchor),
                actualSizeImageView.bottomAnchor.constraint(equalTo: sg.bottomAnchor),
                actualSizeImageView.leadingAnchor.constraint(equalTo: sg.leadingAnchor),
                actualSizeImageView.trailingAnchor.constraint(equalTo: sg.trailingAnchor),
    
                actualSizeImageView.widthAnchor.constraint(equalToConstant: bkgImage.size.width),
                actualSizeImageView.heightAnchor.constraint(equalToConstant: bkgImage.size.height),
    
            ])
    
            origImageView.image = bkgImage
    
            let combinedImage = bkgImage.overlayWith(image: stickerImage, posX: 1000.0, posY: 1000.0)
    
            modImageView.image = combinedImage
    
            actualSizeImageView.image = combinedImage
    
        }
    }
    

    【讨论】:

    • 感谢您的好意回答。我还有一件事,我想让贴纸视图可以旋转、缩放。然后视图的变换被改变。当我调用 overlaywith() 时如何应用转换?是否可以应用转换?
    • @ddaddaddda - 这超出了您最初问题的范围。这是旋转UIImage 的一个很好的例子:stackoverflow.com/a/39804312/6257435 ...关于缩放/缩放,计算“贴纸”图像的所需宽度和高度并修改overlayWith func 以接受该大小(宽度和高度)并使用image.draw(in: CGRect(x: posX, y: posY, width: targetW, height: targetH)) 而不是image.draw(at: ...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    相关资源
    最近更新 更多