问题描述
问题:截图后,通过缩放检查图像模糊.缩放后,图像中的文本似乎模糊.
我知道这个问题已经提出很多次了,但是没有一个人有想要的解决方案.我已经检查了很多帖子,例如
以 10倍
缩放:
该示例的代码:
class ViewController:UIViewController,UIScrollViewDelegate {让zoomLabel:UILabel = UILabel()让scrollView:UIScrollView = UIScrollView()覆盖func viewDidLoad(){super.viewDidLoad()[zoomLabel,scrollView] .forEach {$ 0.translatesAutoresizingMaskIntoConstraints = false}scrollView.addSubview(zoomLabel)view.addSubview(scrollView)让g = view.safeAreaLayoutGuideNSLayoutConstraint.activate([scrollView.centerXAnchor.constraint(等于:g.centerXAnchor),scrollView.centerYAnchor.constraint(等于: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 = .redzoomLabel.backgroundColor = .yellowzoomLabel.font = UIFont.systemFont(ofSize:30.0,weight:.regular)zoomLabel.text =示例文本";scrollView.delegate =自我scrollView.minimumZoomScale = 1scrollView.maximumZoomScale = 10view.backgroundColor = UIColor(白色:0.9,Alpha:1.0)scrollView.backgroundColor = .white}func viewForZooming(在scrollView:UIScrollView中)->UIView?{返回zoomLabel}}
当您捕获视图内容"时,作为 UIImage
,您将获得一个位图,它是视图的大小(以磅为单位) x屏幕比例.
因此,例如,在iPhone 8上,在屏幕尺寸为 @ 2x
的情况下,以 300 x 200
视图将被捕获".作为具有 600 x 400
像素的 UIImage
.
无论是缩放视图本身还是视图的位图捕获,都将得到相同的结果-缩放时边缘模糊.
您的评论包括:……编辑图像时……" -这是一个常见问题,我们希望允许用户添加文本(标签),Bezier路径形状,附加图像等.例如,用户在屏幕上看到的可能是 3000 x 2000
像素的原始图像,显示在 300 x 200
点.在屏幕上 添加一个30点标签看起来不错,但随后将其作为 UIImage
(用于缩放或保存到磁盘)进行抓取,最终得到为 600 x 400
像素的图像,当然,在较大尺寸的图像上看起来效果不佳.
通常,解决此问题的方法如下:
允许用户按屏幕尺寸进行编辑,例如
- 在
300 x 200
视图中显示按比例缩小的3000 x 2000
像素图像 - 添加直角椭圆形的贝塞尔曲线(20,20,200,200)
- 在原点
(32,32)
处添加30点标签
然后,当捕获"时,用于输出/缩放的
- 拍摄原始
3000 x 2000
像素图像 - 添加矩形的贝塞尔曲线(20 * 10、20 * 10、200 * 10、200 * 10)
- 在原点
(32 * 10,32 * 10)
处添加(30 * 10)点标签
另一种选择是进行屏幕编辑 缩小 .
因此,您可以使用 300 x 200
图像视图,以及 3000 x 2000
像素图像(缩放以适合).当用户说我想在rect (20,20,200,200)
中添加一个椭圆形贝塞尔曲线路径时,您的代码会在rect (20 * 10,20* 10、200 * 10、200 * 10)
图像本身,然后刷新图像视图的 .image
属性.
下面是一个更详细的示例,以帮助您弄清楚一切:
class ViewController:UIViewController,UIScrollViewDelegate {让topView:UIView = UIView()让topLabel:UILabel = UILabel()让botView:UIView = UIView()让botLabel:UILabel = UILabel()让topScrollView:UIScrollView = UIScrollView()让botScrollView:UIScrollView = UIScrollView()让topStatLabel:UILabel = UILabel()让botStatLabel:UILabel = UILabel()覆盖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)让g = view.safeAreaLayoutGuideNSLayoutConstraint.activate([topStatLabel.topAnchor.constraint(等于:g.topAnchor,常数:20.0),topStatLabel.leadingAnchor.constraint(equalTo:topScrollView.leadingAnchor),topScrollView.topAnchor.constraint(等于:topStatLabel.bottomAnchor,常数:4.0),topScrollView.centerXAnchor.constraint(等于:g.centerXAnchor),topScrollView.widthAnchor.constraint(equalToConstant:300.0),topScrollView.heightAnchor.constraint(equalToConstant:200.0),botScrollView.topAnchor.constraint(等于:topScrollView.bottomAnchor,常数:12.0),botScrollView.centerXAnchor.constraint(等于:g.centerXAnchor),botScrollView.widthAnchor.constraint(equalToConstant:300.0),botScrollView.heightAnchor.constraint(equalToConstant:200.0),botStatLabel.topAnchor.constraint(等于:botScrollView.bottomAnchor,常数:4.0),botStatLabel.leadingAnchor.constraint(等于: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,常数:8.0),topLabel.leadingAnchor.constraint(equalTo:topView.leadingAnchor,常数:8.0),botLabel.topAnchor.constraint(等于:botView.topAnchor,常数:8.0 * 10.0),botLabel.leadingAnchor.constraint(等于:botView.leadingAnchor,常数: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(等于:botScrollView.contentLayoutGuide.topAnchor),botView.leadingAnchor.constraint(等于:botScrollView.contentLayoutGuide.leadingAnchor),botView.trailingAnchor.constraint(等于:botScrollView.contentLayoutGuide.trailingAnchor),botView.bottomAnchor.constraint(等于:botScrollView.contentLayoutGuide.bottomAnchor),])topLabel.textColor = .redtopLabel.backgroundColor = .yellowtopLabel.font = UIFont.systemFont(ofSize:30.0,weight:.regular)topLabel.text =示例文本";botLabel.textColor = .redbotLabel.backgroundColor = .yellowbotLabel.font = UIFont.systemFont(ofSize:30.0 * 10.0,weight:.regular)botLabel.text =示例文本";topScrollView.delegate =自我topScrollView.minimumZoomScale = 1topScrollView.maximumZoomScale = 10botScrollView.delegate =自我botScrollView.minimumZoomScale = 0.1botScrollView.maximumZoomScale = 1topScrollView.zoomScale = topScrollView.minimumZoomScalebotScrollView.zoomScale = botScrollView.minimumZoomScaleview.backgroundColor = UIColor(白色:0.9,Alpha:1.0)topScrollView.backgroundColor = .whitebotScrollView.backgroundColor = .whitetopStatLabel.font = UIFont.systemFont(ofSize:14,重量:.light)topStatLabel.numberOfLines = 0botStatLabel.font = UIFont.systemFont(ofSize:14,重量:.light)botStatLabel.numberOfLines = 0令t = UITapGestureRecognizer(目标:自我,行动:#selector(self.tapped(_ :)))view.addGestureRecognizer(t)}覆盖func viewDidAppear(_动画:布尔){super.viewDidAppear(动画)updateStatLabels()}func updateStatLabels()->空白 {var sTop ="sTop + =标签点大小:\(topLabel.font.pointSize)"sTop + ="\ n"sTop + =标签框架:\(topLabel.frame)"sTop + ="\ n"sTop + =视图大小:\(topView.bounds.size)"sTop + ="\ n"sTop + =缩放比例:\(String(格式:%0.1f",topScrollView.zoomScale))""var sBot ="sBot + =缩放比例:\(String(格式:%0.1f",botScrollView.zoomScale))"sBot + ="\ n"sBot + =视图大小:\(botView.bounds.size)"sBot + ="\ n"sBot + =标签框架:\(botLabel.frame)";sBot + ="\ n"sBot + =标签点大小:\(botLabel.font.pointSize)"topStatLabel.text = sTopbotStatLabel.text = sBot}func viewForZooming(在scrollView:UIScrollView中)->UIView?{如果scrollView == topScrollView {返回topView}返回botView}使用@objc func(_ g:UITapGestureRecognizer)->空白 {如果Int(topScrollView.zoomScale)== Int(topScrollView.maximumZoomScale){topScrollView.zoomScale = topScrollView.minimumZoomScale} 别的 {topScrollView.zoomScale + = 1}topScrollView.contentOffset = .zero//直接比较浮点数将失败,因此将值取整如果round(botScrollView.zoomScale * 10)== round(botScrollView.maximumZoomScale * 10){botScrollView.zoomScale = botScrollView.minimumZoomScale} 别的 {botScrollView.zoomScale + = 0.1}botScrollView.contentOffset = .zeroupdateStatLabels()}}
顶部滚动视图具有带有30点标签的 300 x 200
视图,允许zoomScale从 1扩展到10
.
底部滚动视图具有带有300点标签的 3000 x 2000
视图,允许zoomScale从 0.1到1.0
.
每次点击屏幕时,scrollViews分别将zoomScale增大1和0.1.
它看起来像这样:
5级和0.5级:
以及10和1.0比例:
PROBLEM: After I take screenshot the image is blurry when check by zooming. The text inside image seems to be blurred when zoomed.
I know this question have been raised many a times but none of them have desired solution. I already checked quite a few post like this one
All the solution been shared so far on this forum are repeated or same in any other way but none of them has a solution for the problem.
Here is what I am doing:
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
}
}
The above function will convert UIView into and image but the image quality returned is not up-to the mark.
You won't get your desired results by doing a UIView
"image capture."
When you zoom a UIScrollView
it does not perform a vector scaling... it performs a rasterized scaling.
You can easily confirm this by using a UILabel
as the viewForZooming
. Here is a label with 30-point system font...
at 1x
zoom:
at 10x
zoom:
Code for that example:
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
}
}
When you "capture the view content" as a UIImage
, you get a bitmap that is the size of the view in points x the screen scale.
So, on an iPhone 8, for example, with @2x
screen scale, at 300 x 200
view will be "captured" as a UIImage
with 600 x 400
pixels.
Whether you zoom the view itself, or a bitmap-capture of the view, you'll get the same result -- blurry edges when zoomed.
Your comments include: "... while editing image ..." -- this is a common issue, where we want to allow the user to add text (labels), Bezier Path shapes, addition images, etc. What the user sees on the screen, for example, may be an original image of 3000 x 2000
pixels, displayed at 300 x 200
points. Adding a 30-point label might look good on the screen, but then grabbing that as a UIImage
(either for zooming or for saving to disk), ends up as a 600 x 400
pixel image which, of course, will not look good at a larger size.
Frequently, the approach to resolve this is along these lines:
Allow the user to edit at screen dimensions, e.g.
- show a
3000 x 2000
pixel image scaled down in a300 x 200
view - add a Bezier Path, oval-in-rect (20, 20, 200, 200)
- add a 30-point label at origin
(32, 32)
Then, when "capturing" that for output / zooming
- take the original
3000 x 2000
pixel image - add a Bezier Path, oval-in-rect (20 * 10, 20 * 10, 200 * 10, 200 * 10)
- add a (30 * 10)-point label at origin
(32 * 10, 32 * 10)
Another option is to do the on-screen editing scaled-down.
So, you might use a 300 x 200
image view, with your 3000 x 2000
pixel image (scale to fit). When the user says "I want to add an oval Bezier Path in rect (20, 20, 200, 200)
, your code would draw that oval at rect (20 * 10, 20 * 10, 200 * 10, 200 * 10)
on the image itself and then refresh the .image
property of the image view.
Here's a little more detailed example to help make things clear:
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()
}
}
The top scroll view has a 300 x 200
view with a 30-point label, allowing zoomScale from 1 to 10
.
The bottom scroll view has a 3000 x 2000
view with a 300-point label, allowing zoomScale from 0.1 to 1.0
.
Each time you tap the screen, the scrollViews increase zoomScale by 1 and 0.1 respectively.
And it looks like this at min-scale:
at 5 and 0.5 scale:
and at 10 and 1.0 scale:
这篇关于如何以编程方式使用UIGraphicsImageRenderer拍摄高质量的屏幕截图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!