简体   繁体   English

iOS 提高 PDF 渲染速度

[英]iOS improve PDF render speed

I'm writing an app that manages documents for a user and (eventually) posts PDF files served out through a web service on the iPhone/iPad.我正在编写一个为用户管理文档的应用程序,并(最终)发布通过 iPhone/iPad 上的 web 服务提供的 PDF 文件。 These are almost exclusively scanned PDF files, and they appear to REALLLLLY bog down the iOS device.这些几乎完全是扫描的 PDF 文件,它们似乎真的让 iOS 设备陷入困境。

The first solution I came up with was to simply host the PDF in a UIWebView.我想出的第一个解决方案是简单地将 PDF 托管在 UIWebView 中。 This works really, really well for "generated" PDF files, but NOT for scanned PDF files (I'm guessing the difference here is raster vs. vector?).这对于“生成的” PDF 文件非常非常有效,但不适用于扫描的 PDF 文件(我猜这里的区别是光栅与矢量?)。

My next solution was to implement a UIDocumentInteractionController, which was said to increase snappiness.我的下一个解决方案是实现一个 UIDocumentInteractionController,据说可以增加敏捷性。 I can report that it does, indeed, seem to be faster than UIWebView, but it's still unacceptably slow, even on smallish, 2 page PDF files.我可以报告它确实似乎比 UIWebView 快,但它仍然慢得令人无法接受,即使在较小的 2 页 PDF 文件上也是如此。 (On a side note, the "auto-open-in-another-app" feature, along with built-in printing is super slick!) (附带说明,“在另一个应用程序中自动打开”功能以及内置打印功能非常棒!)

I've read a post or 2 about the QuickLook framework, and I plan to look into that, but I've also stumbled across a few posts talking about CGPDFDocument classes and such.我已经阅读了一篇或两篇关于 QuickLook 框架的文章,我打算研究一下,但我也偶然发现了一些关于 CGPDFDocument 类等的文章。 Those seem to have a finer control over document navigation (a la xPdf), but I have no idea where to start with that.那些似乎对文档导航(la xPdf)有更好的控制,但我不知道从哪里开始。 Plus, I'm not even sure if it offers a performance benefit for what I'm doing.另外,我什至不确定它是否为我正在做的事情提供了性能优势。

So, first question: what's the fastest way to render scanned PDF files on the iPhone/iPad?那么,第一个问题:在 iPhone/iPad 上渲染扫描的 PDF 文件的最快方法是什么?

Second question: The scanned PDF files are generated by my company, so I have some control over the PDF generation settings.第二个问题:扫描的PDF文件是我公司生成的,所以我对PDF的生成设置有一定的控制权。 Does anybody know what settings might improve load speed for image-based PDF files?有谁知道哪些设置可以提高基于图像的 PDF 文件的加载速度?

Thanks!谢谢!

(By the way: I've been coding for 19 hours straight today, so if I rambled or didn't make sense, please forgive me: :) ) (顺便说一句:我今天已经连续编码了 19 个小时,所以如果我漫无目的或没有意义,请原谅我::))

The fastest solution will be to write your own custom pdf parser and rendering framework using the CGPDFDocument classes.最快的解决方案是使用 CGPDFDocument 类编写您自己的自定义 pdf 解析器和呈现框架。 The secret to superfast pdf rendering is using techniques like:超快 pdf 渲染的秘诀是使用以下技术:

  • Off-screen rendering of full-size pages to images.全尺寸页面到图像的屏幕外渲染。
  • Only activate CATiledLayer drawing after a certain zoom level.仅在特定缩放级别后激活 CATiledLayer 绘图。 When the user views your pdf page at the default zoom level there's no need to activate the CATiledLayer drawing because it's very expensive.当用户以默认缩放级别查看您的 pdf 页面时,无需激活 CATiledLayer 绘图,因为它非常昂贵。 Just display the already off-screen rendered image.只需显示已经离屏渲染的图像。 When the user starts zooming in you can activate the CATiledLayer.当用户开始放大时,您可以激活 CATiledLayer。
  • Using a smart algorithm to cache off-screen rendered pdf pages.使用智能算法缓存离屏渲染的 pdf 页面。 You can cache the previous and next pages as off-screen rendered images.您可以将前一页和后一页缓存为屏幕外渲染图像。
  • On fast devices (iPhone 4 or greater and iPad 2 or greater) you can start a background job that will render all pages off-screen and save them to disk.在快速设备(iPhone 4 或更高版本和 iPad 2 或更高版本)上,您可以启动后台作业,将所有页面呈现在屏幕外并将它们保存到磁盘。
  • Cache regularly used information about pdf pages like: original rect, rotation, rotated rect etc.缓存有关 pdf 页面的常用信息,例如:原始矩形、旋转、旋转矩形等。
  • You'll use a lot of CGPDFPageRef objects.您将使用很多 CGPDFPageRef 对象。 It's important to know that this will increase memory usage a lot.重要的是要知道这会大大增加 memory 的使用量。 A little trick is to close and re-open the CGPDFDocumentRef object when you receive a memory warning.一个小技巧是在收到 memory 警告时关闭并重新打开 CGPDFDocumentRef object。

I used all of the above mentioned techniques in PDFTouch SDK for iOS which is a fast pdf rendering framework developed by me!我在PDFTouch SDK for iOS中使用了上述所有技术,这是我开发的快速 pdf 渲染框架!

You may wanna try to reduce image size.您可能想尝试减小图像大小。 Large PDFs are really pushing the iPad/iPhone to its limits.大型 PDF 确实将 iPad/iPhone 推向了极限。 Of course this means that you need to draw/manage the pdf yourself, with Quartz calls.当然,这意味着您需要通过 Quartz 调用自己绘制/管理 pdf。

More speed is possible with proper caching.使用适当的缓存可以提高速度。 You can render pages off-screen, and display them without opening the actual pdf - which is much, much faster.您可以在屏幕外渲染页面,并在不打开实际 pdf 的情况下显示它们——这要快得多。

if you get desperate you could re-process the pdf files on your server to turn them into simple image files (associated with the original pdf files) then load those.如果您感到绝望,您可以重新处理服务器上的 pdf 文件,将它们转换为简单的图像文件(与原始 pdf 文件相关联)然后加载这些文件。 that way no "pdf" parsing needs to take place.这样就不需要进行“pdf”解析。 and then you can host on the server or include as part of the app if the volume is low.然后您可以在服务器上托管或在音量较低时将其作为应用程序的一部分包含在内。

basically you'd need a server script that does all the re-processing and sticks the new files into a special folder.基本上,您需要一个服务器脚本来执行所有重新处理并将新文件粘贴到一个特殊文件夹中。 maybe you make a database to reference the new files.也许您创建一个数据库来引用新文件。 or maybe you create a directory name for each new file that mirrors the original pdf file name.或者,您可以为每个新文件创建一个目录名,以反映原始 pdf 文件名。

By using UIWebView to render the pdf, we will not get proper control over the pdf.通过使用 UIWebView 渲染 pdf,我们将无法正确控制 pdf。 like we cannot go to the desired page directly.就像我们不能 go 直接到所需的页面。 and we cannot search a particular word and highlight.我们无法搜索特定的单词并突出显示。

its better to use CGPDF classes like CGPDFDocumentRef and CGPDFPageRef to handle the pdf documents properly.最好使用 CGPDFDocumentRef 和 CGPDFPageRef 等 CGPDF 类来正确处理 pdf 文档。

Using these classes we have two options to handle the pdf's.使用这些类,我们有两个选项来处理 pdf。 1. extracting the pdf pages as images individually and display using UIImageView. 1. 将 pdf 页面单独提取为图像并使用 UIImageView 显示。 2. extract the content of each page using CGPDFPageRef and create pdf for each page at runtime and display on to the webview.(better control control over pdf and neat display) 2.使用CGPDFPageRef提取每个页面的内容并在运行时为每个页面创建pdf并显示到webview上。(更好的控制控制Z437175BA4191210EE004E1D93749和显示)

below is the sample code to extract individual page as an image.下面是将单个页面提取为图像的示例代码。

-(UIImage *)getPage : (NSString*) filePath{

    const char *myBuffer           = (const char*)filePath;                        // PDF Path
    CFStringRef urlString          = (CFStringRef)myBuffer;
    CFURLRef url                   = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlString, 2, NO);  
    CGPDFDocumentRef myDocumentRef = CGPDFDocumentCreateWithURL(url);

    CGPDFPageRef myPageRef         = CGPDFDocumentGetPage(myDocumentRef, 1);
    CGRect pdfcropBox              = CGPDFPageGetBoxRect(myPageRef,kCGPDFCropBox); //kCGPDFCropBox

    UIGraphicsBeginImageContext      (pdfcropBox.size);
    CGContextRef context           = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM            (context,0,pdfcropBox.size.height);// [self pageRect].origin.x,[self pageRect].origin.y+[self pageRect].size.height); //320);
    // scale 1:1 100%
    CGContextScaleCTM                (context, 1.0, -1.0);
    CGContextSaveGState              (context);
    CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(myPageRef, kCGPDFCropBox, CGRectMake(0, 0, pdfcropBox.size.width,pdfcropBox.size.height), 0, true);  //
    CGContextConcatCTM               (context, pdfTransform);
    CGContextDrawPDFPage             (context, myPageRef);
    CGContextRestoreGState           (context);

    UIImage *resultingImage        = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext        ();
    CGPDFDocumentRelease             (myDocumentRef);

    //CGPDFPageRelease(myPageRef);
        //myPageRef   = nil;
    myDocumentRef = nil;
    urlString     = nil;
    url           = nil;
    return resultingImage;
}

Here are my 2 cents about easy and fast pdf rendering in swift.这是我关于在 swift 中简单快速的 pdf 渲染的 2 美分。

SwiftyPDF SwiftyPDF

  • Paging with system UIPageViewController使用系统 UIPageViewController 进行分页
  • Zooming with UIScrollView zooming features使用 UIScrollView 缩放功能进行缩放
  • Renders the PDF fast by converting the page to placeholder image通过将页面转换为占位符图像来快速呈现 PDF
  • PDF page is scaled and divided into small tiles. PDF 页面被缩放并分成小图块。 Tiles are cached to image files and rendered over the placeholder image (using the CATiledLayer)切片缓存到图像文件并在占位符图像上渲染(使用 CATiledLayer)

Still WIP仍然在制品

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

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