【问题标题】:iOS improve PDF render speediOS 提升 PDF 渲染速度
【发布时间】:2011-05-29 04:43:54
【问题描述】:

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

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

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

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

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

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

谢谢!

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

【问题讨论】:

  • 有您可以为我们上传的示例 PDF 吗?很可能与使用的 TIFF 压缩类型有关(假设纸张最初被扫描为 TIFF)。

标签: iphone ios ipad pdf render


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

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

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

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

        【讨论】:

          【解决方案5】:

          这是我关于在 swift 中轻松快速地呈现 pdf 的 2 美分。

          SwiftyPDF

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

          仍在进行中

          【讨论】:

            猜你喜欢
            • 2012-06-06
            • 2015-05-23
            • 2016-11-17
            • 1970-01-01
            • 1970-01-01
            • 2014-12-07
            • 2011-08-12
            • 2011-07-21
            • 1970-01-01
            相关资源
            最近更新 更多