簡體   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