Monday, October 19, 2015 / PDF, Swift

PDFをページごとにPNG画像に変換( swift 編 )

PDFをページごとにPNG画像に変換してみた話。 Swift で実装。

複数のPNG画像からPDFを生成する の逆の処理。 このエントリーで生成した concat-png.pdf からページごとにPNGデータを生成する。

pdf-to-png

swiftc によりコマンドラインからビルドできるのはありがたい。

Xcode 7.0.1 環境で... hello.swift ファイルに

print("hello")

と書いて

$ swiftc -o hello hello.swift

とすれば実行ファイルを生成できる。

extractPng.swift

import Foundation
import CoreFoundation
import CoreImage

let path = NSProcessInfo.processInfo().arguments[1]
let url:NSURL  = NSURL(fileURLWithPath: path) as CFURLRef
let pdfDocument = CGPDFDocumentCreateWithURL(url) // CGPDFDocument

//
// save each page into png file.
//

let pageCount = CGPDFDocumentGetNumberOfPages(pdfDocument)
for index in 1...pageCount {

    let page = CGPDFDocumentGetPage(pdfDocument, index) // CGPDFPage

    let colorSpace = CGColorSpaceCreateDeviceRGB() // CGColorSpace
    let bitmapInfo = CGImageAlphaInfo.PremultipliedFirst

    let mediaBoxRect = CGPDFPageGetBoxRect(page, CGPDFBox.MediaBox) // CGRect
    let w = Int( mediaBoxRect.size.width )
    let h = Int( mediaBoxRect.size.height )

    let context = CGBitmapContextCreate(
       nil,
       w, h, 8, 0, colorSpace, bitmapInfo.rawValue)

    CGContextDrawPDFPage(context, page)

    let image = CGBitmapContextCreateImage(context) //CGImageRef
    let dataProvider = CGImageGetDataProvider( image ) // CGDataProviderRef
    let data = CGDataProviderCopyData(dataProvider)
    let imageType = kUTTypePNG

    let savePngFilename = "page-" + String(index) + ".png"
    let savePngFileUrl:NSURL  = NSURL(fileURLWithPath: savePngFilename) as CFURLRef

    let file = CGImageDestinationCreateWithURL( savePngFileUrl, imageType, 1, nil ) 
    print( file ) // CGImageDestination

    let options: [NSString:AnyObject] = [
       kCGImagePropertyOrientation : 1,
       kCGImagePropertyHasAlpha : true,
       kCGImageDestinationLossyCompressionQuality : 0.80]

    CGImageDestinationAddImage(file!, image!, options)
    CGImageDestinationFinalize(file!)
}

実行

swiftc -o extractPng extractPng.swift
./extractPng input.pdf

Groovyと比べて速い。ビルドと実行が一瞬。 Core Graphics のAPIに精通していく必要があるがPDF操作関連は Groovy + PDFBox などで処理するよりよいかもしれない。 Swift2 が Linux でも作動するようになればなお良い。 そのとき Core Graphics などの関連ライブラリも移植されるのだろうか…