gpt4 book ai didi

ios - 如何以编程方式使用 UIGraphicsImageRenderer 拍摄高质量的屏幕截图?

转载 作者:行者123 更新时间:2023-12-04 03:44:31 30 4
gpt4 key购买 nike

问题 : 在我截取屏幕截图后,通过缩放检查时图像模糊。放大时图像内的文字似乎模糊不清。
我知道这个问题已经被提出很多次了,但他们都没有想要的解决方案。我已经检查了很多帖子,例如 this one
迄今为止在此论坛上共享的所有解决方案都以任何其他方式重复或相同,但没有一个解决方案可以解决问题。
这是我在做什么:

extension UIView {

func asImage() -> UIImage? {
let format = UIGraphicsImageRendererFormat()
format.opaque = self.isOpaque
let renderer = UIGraphicsImageRenderer(bounds: bounds,format: format)
return renderer.image(actions: { rendererContext in
layer.render(in: rendererContext.cgContext)
})
}

//The other option using UIGraphicsEndImageContext

func asImage() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
self.layer.render(in: context)
return UIGraphicsGetImageFromCurrentImageContext()
}
return nil
}
}
上述函数将 UIView 转换为图像,但返回的图像质量达不到标准。

最佳答案

执行 UIView 不会得到您想要的结果“图像捕捉。”
当您缩放 UIScrollView确实如此 不是 执行矢量缩放...它执行光栅化缩放。
您可以使用 UILabel 轻松确认这一点。如 viewForZooming .这是一个带有 30 磅系统字体的标签...
1x飞涨:
enter image description here
10x飞涨:
enter image description here
该示例的代码:

class ViewController: UIViewController, UIScrollViewDelegate {

let zoomLabel: UILabel = UILabel()
let scrollView: UIScrollView = UIScrollView()

override func viewDidLoad() {
super.viewDidLoad()

[zoomLabel, scrollView].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}

scrollView.addSubview(zoomLabel)
view.addSubview(scrollView)

let g = view.safeAreaLayoutGuide

NSLayoutConstraint.activate([

scrollView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
scrollView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
scrollView.widthAnchor.constraint(equalToConstant: 300.0),
scrollView.heightAnchor.constraint(equalToConstant: 200.0),

zoomLabel.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
zoomLabel.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
zoomLabel.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
zoomLabel.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),

])

zoomLabel.textColor = .red
zoomLabel.backgroundColor = .yellow
zoomLabel.font = UIFont.systemFont(ofSize: 30.0, weight: .regular)
zoomLabel.text = "Sample Text"

scrollView.delegate = self
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 10

view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
scrollView.backgroundColor = .white
}


func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return zoomLabel
}

}
当您“捕获 View 内容”作为 UIImage ,你会得到一个位图,它是 View 的大小,以点 x 屏幕比例为单位。
例如,在 iPhone 8 上,使用 @2x屏幕比例,在 300 x 200 View 将被“捕获”为 UIImage600 x 400像素。
无论您缩放 View 本身,还是 View 的位图捕获,您都会得到相同的结果——缩放时边缘模糊。
您的评论包括:“...在编辑图像时...”——这是一个常见问题,我们希望允许用户添加文本(标签)、贝塞尔路径形状、添加图像等。用户看到的内容例如,屏幕上可能是 3000 x 2000的原始图像像素,显示在 300 x 200点。添加一个 30 点的标签可能在屏幕上看起来不错,但随后将其抓取为 UIImage (用于缩放或保存到磁盘),最终为 600 x 400像素图像,当然,在更大的尺寸下看起来不太好。
通常,解决此问题的方法是:
允许用户在屏幕尺寸上进行编辑,例如
  • 显示 3000 x 2000像素图像按比例缩小 300 x 200查看
  • 添加贝塞尔路径,矩形矩形 (20, 20, 200, 200)
  • 在原点添加 30 点标签 (32, 32)

  • 然后,当“捕获”输出/缩放时
  • 取原版3000 x 2000像素图像
  • 添加贝塞尔路径,矩形矩形 (20 * 10, 20 * 10, 200 * 10, 200 * 10)
  • 在原点添加 (30 * 10) 点标签 (32 * 10, 32 * 10)

  • 另一种选择是进行屏幕编辑 缩小版 .
    因此,您可以使用 300 x 200 ImageView ,与您的 3000 x 2000像素图像(缩放以适合)。当用户说“我想在 rect (20, 20, 200, 200) 中添加一个椭圆形贝塞尔路径”时,您的代码将在图像本身的 rect (20 * 10, 20 * 10, 200 * 10, 200 * 10) 处绘制该椭圆,然后刷新 ImageView 的 .image 属性。
    这是一个更详细的示例,以帮助您清楚地了解情况:
    class ViewController: UIViewController, UIScrollViewDelegate {

    let topView: UIView = UIView()
    let topLabel: UILabel = UILabel()

    let botView: UIView = UIView()
    let botLabel: UILabel = UILabel()

    let topScrollView: UIScrollView = UIScrollView()
    let botScrollView: UIScrollView = UIScrollView()

    let topStatLabel: UILabel = UILabel()
    let botStatLabel: UILabel = UILabel()

    override func viewDidLoad() {
    super.viewDidLoad()

    [topView, topLabel, botView, botLabel, topScrollView, botScrollView, topStatLabel, botStatLabel].forEach {
    $0.translatesAutoresizingMaskIntoConstraints = false
    }

    topView.addSubview(topLabel)
    botView.addSubview(botLabel)

    topScrollView.addSubview(topView)
    botScrollView.addSubview(botView)

    view.addSubview(topStatLabel)
    view.addSubview(botStatLabel)

    view.addSubview(topScrollView)
    view.addSubview(botScrollView)

    let g = view.safeAreaLayoutGuide

    NSLayoutConstraint.activate([

    topStatLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
    topStatLabel.leadingAnchor.constraint(equalTo: topScrollView.leadingAnchor),

    topScrollView.topAnchor.constraint(equalTo: topStatLabel.bottomAnchor, constant: 4.0),
    topScrollView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
    topScrollView.widthAnchor.constraint(equalToConstant: 300.0),
    topScrollView.heightAnchor.constraint(equalToConstant: 200.0),

    botScrollView.topAnchor.constraint(equalTo: topScrollView.bottomAnchor, constant: 12.0),
    botScrollView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
    botScrollView.widthAnchor.constraint(equalToConstant: 300.0),
    botScrollView.heightAnchor.constraint(equalToConstant: 200.0),

    botStatLabel.topAnchor.constraint(equalTo: botScrollView.bottomAnchor, constant: 4.0),
    botStatLabel.leadingAnchor.constraint(equalTo: botScrollView.leadingAnchor),

    topView.widthAnchor.constraint(equalToConstant: 300.0),
    topView.heightAnchor.constraint(equalToConstant: 200.0),

    botView.widthAnchor.constraint(equalToConstant: 300.0 * 10.0),
    botView.heightAnchor.constraint(equalToConstant: 200.0 * 10.0),

    topLabel.topAnchor.constraint(equalTo: topView.topAnchor, constant: 8.0),
    topLabel.leadingAnchor.constraint(equalTo: topView.leadingAnchor, constant: 8.0),

    botLabel.topAnchor.constraint(equalTo: botView.topAnchor, constant: 8.0 * 10.0),
    botLabel.leadingAnchor.constraint(equalTo: botView.leadingAnchor, constant: 8.0 * 10.0),

    topView.topAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.topAnchor),
    topView.leadingAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.leadingAnchor),
    topView.trailingAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.trailingAnchor),
    topView.bottomAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.bottomAnchor),

    botView.topAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.topAnchor),
    botView.leadingAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.leadingAnchor),
    botView.trailingAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.trailingAnchor),
    botView.bottomAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.bottomAnchor),

    ])

    topLabel.textColor = .red
    topLabel.backgroundColor = .yellow
    topLabel.font = UIFont.systemFont(ofSize: 30.0, weight: .regular)
    topLabel.text = "Sample Text"

    botLabel.textColor = .red
    botLabel.backgroundColor = .yellow
    botLabel.font = UIFont.systemFont(ofSize: 30.0 * 10.0, weight: .regular)
    botLabel.text = "Sample Text"

    topScrollView.delegate = self
    topScrollView.minimumZoomScale = 1
    topScrollView.maximumZoomScale = 10

    botScrollView.delegate = self
    botScrollView.minimumZoomScale = 0.1
    botScrollView.maximumZoomScale = 1

    topScrollView.zoomScale = topScrollView.minimumZoomScale
    botScrollView.zoomScale = botScrollView.minimumZoomScale

    view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
    topScrollView.backgroundColor = .white
    botScrollView.backgroundColor = .white

    topStatLabel.font = UIFont.systemFont(ofSize: 14, weight: .light)
    topStatLabel.numberOfLines = 0
    botStatLabel.font = UIFont.systemFont(ofSize: 14, weight: .light)
    botStatLabel.numberOfLines = 0

    let t = UITapGestureRecognizer(target: self, action: #selector(self.tapped(_:)))
    view.addGestureRecognizer(t)
    }

    override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    updateStatLabels()
    }

    func updateStatLabels() -> Void {
    var sTop = ""
    sTop += "Label Point Size: \(topLabel.font.pointSize)"
    sTop += "\n"
    sTop += "Label Frame: \(topLabel.frame)"
    sTop += "\n"
    sTop += "View Size: \(topView.bounds.size)"
    sTop += "\n"
    sTop += "Zoom Scale: \(String(format: "%0.1f", topScrollView.zoomScale))"

    var sBot = ""
    sBot += "Zoom Scale: \(String(format: "%0.1f", botScrollView.zoomScale))"
    sBot += "\n"
    sBot += "View Size: \(botView.bounds.size)"
    sBot += "\n"
    sBot += "Label Frame: \(botLabel.frame)"
    sBot += "\n"
    sBot += "Label Point Size: \(botLabel.font.pointSize)"

    topStatLabel.text = sTop
    botStatLabel.text = sBot
    }

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    if scrollView == topScrollView {
    return topView
    }
    return botView
    }

    @objc func tapped(_ g: UITapGestureRecognizer) -> Void {

    if Int(topScrollView.zoomScale) == Int(topScrollView.maximumZoomScale) {
    topScrollView.zoomScale = topScrollView.minimumZoomScale
    } else {
    topScrollView.zoomScale += 1
    }
    topScrollView.contentOffset = .zero

    // comparing floating point directly will fail, so round the values
    if round(botScrollView.zoomScale * 10) == round(botScrollView.maximumZoomScale * 10) {
    botScrollView.zoomScale = botScrollView.minimumZoomScale
    } else {
    botScrollView.zoomScale += 0.1
    }

    botScrollView.contentOffset = .zero

    updateStatLabels()
    }

    }
    顶部 ScrollView 有一个 300 x 200带有 30 点标签的 View ,允许从 1 to 10 缩放比例.
    底部 ScrollView 有一个 3000 x 2000带有 300 点标签的 View ,允许从 0.1 to 1.0 缩放比例.
    每次点击屏幕时,scrollViews 都会将 zoomScale 分别增加 1 和 0.1。
    它在最小尺度上看起来像这样:
    enter image description here
    在 5 和 0.5 级:
    enter image description here
    并在 10 和 1.0 比例下:
    enter image description here

    关于ios - 如何以编程方式使用 UIGraphicsImageRenderer 拍摄高质量的屏幕截图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65392607/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com