繁体   English   中英

iOS 提高 PDF 渲染速度

[英]iOS improve PDF render speed

我正在编写一个为用户管理文档的应用程序,并(最终)发布通过 iPhone/iPad 上的 web 服务提供的 PDF 文件。 这些几乎完全是扫描的 PDF 文件,它们似乎真的让 iOS 设备陷入困境。

我想出的第一个解决方案是简单地将 PDF 托管在 UIWebView 中。 这对于“生成的” PDF 文件非常非常有效,但不适用于扫描的 PDF 文件(我猜这里的区别是光栅与矢量?)。

我的下一个解决方案是实现一个 UIDocumentInteractionController,据说可以增加敏捷性。 我可以报告它确实似乎比 UIWebView 快,但它仍然慢得令人无法接受,即使在较小的 2 页 PDF 文件上也是如此。 (附带说明,“在另一个应用程序中自动打开”功能以及内置打印功能非常棒!)

我已经阅读了一篇或两篇关于 QuickLook 框架的文章,我打算研究一下,但我也偶然发现了一些关于 CGPDFDocument 类等的文章。 那些似乎对文档导航(la xPdf)有更好的控制,但我不知道从哪里开始。 另外,我什至不确定它是否为我正在做的事情提供了性能优势。

那么,第一个问题:在 iPhone/iPad 上渲染扫描的 PDF 文件的最快方法是什么?

第二个问题:扫描的PDF文件是我公司生成的,所以我对PDF的生成设置有一定的控制权。 有谁知道哪些设置可以提高基于图像的 PDF 文件的加载速度?

谢谢!

(顺便说一句:我今天已经连续编码了 19 个小时,所以如果我漫无目的或没有意义,请原谅我::))

最快的解决方案是使用 CGPDFDocument 类编写您自己的自定义 pdf 解析器和呈现框架。 超快 pdf 渲染的秘诀是使用以下技术:

  • 全尺寸页面到图像的屏幕外渲染。
  • 仅在特定缩放级别后激活 CATiledLayer 绘图。 当用户以默认缩放级别查看您的 pdf 页面时,无需激活 CATiledLayer 绘图,因为它非常昂贵。 只需显示已经离屏渲染的图像。 当用户开始放大时,您可以激活 CATiledLayer。
  • 使用智能算法缓存离屏渲染的 pdf 页面。 您可以将前一页和后一页缓存为屏幕外渲染图像。
  • 在快速设备(iPhone 4 或更高版本和 iPad 2 或更高版本)上,您可以启动后台作业,将所有页面呈现在屏幕外并将它们保存到磁盘。
  • 缓存有关 pdf 页面的常用信息,例如:原始矩形、旋转、旋转矩形等。
  • 您将使用很多 CGPDFPageRef 对象。 重要的是要知道这会大大增加 memory 的使用量。 一个小技巧是在收到 memory 警告时关闭并重新打开 CGPDFDocumentRef object。

我在PDFTouch SDK for iOS中使用了上述所有技术,这是我开发的快速 pdf 渲染框架!

您可能想尝试减小图像大小。 大型 PDF 确实将 iPad/iPhone 推向了极限。 当然,这意味着您需要通过 Quartz 调用自己绘制/管理 pdf。

使用适当的缓存可以提高速度。 您可以在屏幕外渲染页面,并在不打开实际 pdf 的情况下显示它们——这要快得多。

如果您感到绝望,您可以重新处理服务器上的 pdf 文件,将它们转换为简单的图像文件(与原始 pdf 文件相关联)然后加载这些文件。 这样就不需要进行“pdf”解析。 然后您可以在服务器上托管或在音量较低时将其作为应用程序的一部分包含在内。

基本上,您需要一个服务器脚本来执行所有重新处理并将新文件粘贴到一个特殊文件夹中。 也许您创建一个数据库来引用新文件。 或者,您可以为每个新文件创建一个目录名,以反映原始 pdf 文件名。

通过使用 UIWebView 渲染 pdf,我们将无法正确控制 pdf。 就像我们不能 go 直接到所需的页面。 我们无法搜索特定的单词并突出显示。

最好使用 CGPDFDocumentRef 和 CGPDFPageRef 等 CGPDF 类来正确处理 pdf 文档。

使用这些类,我们有两个选项来处理 pdf。 1. 将 pdf 页面单独提取为图像并使用 UIImageView 显示。 2.使用CGPDFPageRef提取每个页面的内容并在运行时为每个页面创建pdf并显示到webview上。(更好的控制控制Z437175BA4191210EE004E1D93749和显示)

下面是将单个页面提取为图像的示例代码。

-(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;
}

这是我关于在 swift 中简单快速的 pdf 渲染的 2 美分。

SwiftyPDF

  • 使用系统 UIPageViewController 进行分页
  • 使用 UIScrollView 缩放功能进行缩放
  • 通过将页面转换为占位符图像来快速呈现 PDF
  • PDF 页面被缩放并分成小图块。 切片缓存到图像文件并在占位符图像上渲染(使用 CATiledLayer)

仍然在制品

暂无
暂无

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

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