如何将复杂的UIView渲染成具有高分辨率的PDF上下文? [英] How to render a complex UIView into a PDF Context with high resolution?

查看:85
本文介绍了如何将复杂的UIView渲染成具有高分辨率的PDF上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于如何将UIView呈现为PDF上下文,有几个问题,但它们都使用view.layer.renderInContext(pdfContext),这会产生72 DPI图像(以及打印时看起来很糟糕的图像)。我正在寻找的是一种技术,以某种方式让UIView渲染类似于300 DPI。

There are several questions on SO asking how to render a UIView into a PDF context, but they all use view.layer.renderInContext(pdfContext), which results in a 72 DPI image (and one that looks terrible when printed). What I'm looking for is a technique to somehow get the UIView to render at something like 300 DPI.

推荐答案

最终,我能够从几个先前的帖子中提取并提出一个解决方案。我发布这个因为我花了很长时间才开始工作,我真的希望能节省别人的时间和精力。

In the end, I was able to take hints from several prior posts and put together a solution. I'm posting this since it took me a long time to get working, and I really hope to save someone else time and effort doing the same.

此解决方案使用两个基本技巧:

This solution uses two basic techniques:


  1. 将UIView渲染成缩放的位图上下文以生成大图像

  2. Draw将图像缩小为PDF上下文,使绘制的图像具有高分辨率

构建视图:

let v = UIView()
... // then add subviews, constraints, etc

创建PDF上下文:

UIGraphicsBeginPDFContextToData(data, docRect, stats.headerDict) // zero == (612 by 792 points)

defer { UIGraphicsEndPDFContext() }

UIGraphicsBeginPDFPage();

guard let pdfContext = UIGraphicsGetCurrentContext() else { return nil }

// I tried 300.0/72.0 but was not happy with the results
let rescale: CGFloat = 4 // 288 DPI rendering of VIew

// You need to change the scale factor on all subviews, not just the top view!
// This is a vital step, and there may be other types of views that need to be excluded

然后使用扩展比例创建图像的大位图:

Then create a large bitmap of the image with an expanded scale:

func scaler(v: UIView) {
   if !v.isKindOfClass(UIStackView.self) {
      v.contentScaleFactor = 8
   }
   for sv in v.subviews {
      scaler(sv)
   }
}
scaler(v)

// Create a large Image by rendering the scaled view
let bigSize = CGSize(width: v.frame.size.width*rescale, height: v.frame.size.height*rescale)
UIGraphicsBeginImageContextWithOptions(bigSize, true, 1)
let context = UIGraphicsGetCurrentContext()!

CGContextSetFillColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextFillRect(context, CGRect(origin: CGPoint(x: 0, y: 0), size: bigSize))

// Must increase the transform scale
CGContextScaleCTM(context, rescale, rescale)

v.layer.renderInContext(context)

let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

现在我们每个点都有一个大图像代表一个像素。
要以高分辨率将其绘制到PDF中,我们需要缩小PDF,同时以大尺寸绘制图像:

Now we have a large image with each point representing one pixel. To get it drawn into the PDF at high resolution, we need to scale the PDF down while drawing the image at its large size:

CGContextSaveGState(pdfContext)
CGContextTranslateCTM(pdfContext, v.frame.origin.x, v.frame.origin.y) // where the view should be shown

CGContextScaleCTM(pdfContext, 1/rescale, 1/rescale)

let frame = CGRect(origin: CGPoint(x: 0, y: 0), size: bigSize)
image.drawInRect(frame)

CGContextRestoreGState(pdfContext)

... // Continue with adding other items

你可以看到奶油色位图中包含的左边S与绘制的S相比看起来相当不错,但是属性字符串:

You can see that the left "S" contained in the cream colored bitmap looks pretty nice compared to a "S" drawn but an attributed string:

当通过简单的PDF渲染查看相同的PDF而不进行所有缩放时,这就是你的意思会看到:

When the same PDF is viewed by a simple rendering of the PDF without all the scaling, this is what you would see:

这篇关于如何将复杂的UIView渲染成具有高分辨率的PDF上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆