在iOS devices上分割PDF檔

在iOS上要畫出一頁PDF,其實Cocoa Framwork就已經有提供一些操作繪出PDF檔案所需的基本功能,定義在CoreGraphics裡,在這篇裡,我們要把一個完整的PDF讀出來,並且把它切成一頁一個檔案,然後存回iOS的file system,用這樣的範利來學一下怎樣操作PDF。

Note: 這篇是三年前寫的文章,如果有deprecated functions,歡迎回報!

Note2: 當然整篇文章現在看起來慘不忍睹,所以基本上我是重寫過了,但方法是不變的

Note3: 一台大手機,但不會爆炸

基本知識: Context

在CoreGraphics裡面,context代表的是畫圖所需要的環境設定,你可以把它理解為一個桌面,上面有畫布、有調好色的顏料等,context會用一個CGContext物件作為代表。在開始畫圖前,會先執行Context Begin,表示這之後的一切行為都會呈現在這個context底下。當然,在畫完圖後也需要Context Close,表示結束繪圖的行為,後面的指令就完全不會影響到你這個context的內容。

讀取PDF

首先我們要先產生一個能夠讀取PDF檔的reference,所以就用以下的方式

CGPDFDocumentRef SourcePDFDocument = CGPDFDocumentCreateWithURL((__bridge CFURLRef)sourcePDFUrl);

其中sourcePDFUrl就是PDF檔的URL,之後我們會利用這個reference來讀取原始的PDF檔案。接下來我們要做的,就是從原始檔中,一頁一頁把資料讀出來,並且繪製成n個新的PDF檔。

size_t numberOfPages = CGPDFDocumentGetNumberOfPages(SourcePDFDocument); //取得原始PDF總頁數

上面這一步會取出PDF檔的總頁數,總頁數是我們要拿來跑一頁一頁的for迴圈用的。

接下來我們針對每一頁PDF,都產生一個context,也就是開一個新的環境,並且把PDF資料從原始檔裡拿出來,畫在我們的context之中。

for(int currentPage = 1; currentPage <= numberOfPages; currentPage ++ ){
    [self drawPage:currentPage];
}

最後要記得把retain的PDF reference給release掉,就大功告成啦。

CGPDFDocumentRelease(SourcePDFDocument);

好的,相信聰明的你已經發現,我們的精華,都藏在(drawPage:)那裡了!快去找吧!

Drawing pages

在繪製每一頁的時候,基本上的邏輯很簡單,就是我們會先開起一個空白的context,然後把某一頁PDF資料讀出來,畫在剛開好的那個context底下,並且把這個context的所有內容存成一個檔案。接下來會先介紹幾個基本functions。

  • 透過CGPDFContextCreateWithURL,我們可以產生一個空白的context,供我們等一下要繪製資料用
  • 利用CGPDFDocumentGetPage這個方法,可以拿到原始檔案特定一頁的reference
  • CGContextDrawPDFPage這個方法則是可以將reference中的內容繪製到特定的context底下。

下面是完整的程式碼:


- (void)drawPage:(int)i {
    CFURLRef pdfURLOutput = (CFURLRef)CFBridgingRetain([NSURL fileURLWithPath:targetPath]);
   
     /* 宣告一個新的context,並且指明這個context即將被寫到某個URL底下 */
    CGContextRef writeContext = CGPDFContextCreateWithURL(pdfURLOutput, NULL, NULL);

    /* 取得特定頁的reference */
    CGPDFPageRef page = CGPDFDocumentGetPage(SourcePDFDocument, i);
    CGRect  mediaBox = CGPDFPageGetBoxRect(page, kCGPDFTrimBox);

    /* 把剛剛取到的頁面內容畫到我們新產生的context下 */
    CGContextBeginPage(writeContext, &mediaBox);
    CGContextDrawPDFPage(writeContext, page);
    CGContextEndPage(writeContext);

    /* 把context close掉,檔案就會被存進檔案系統之中 */
    CGPDFContextClose(writeContext);

    CGContextRelease(writeContext);
    CFRelease(pdfURLOutput);
}

要注意的是最後一定要下close,檔案才會被寫入。還有使用任何的CG物件,都一定要release!

以上就是將PDF切成一頁一個檔案的流程,歡迎討論。

除了上面提供的方式之外,apple的dev上面其實提到了不太一樣的做法。可以參考(https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/GeneratingPDF/GeneratingPDF.html)

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s