PDFをページごとにPNG画像に変換してみた話。 Swift で実装。
複数のPNG画像からPDFを生成する の逆の処理。 このエントリーで生成した concat-png.pdf からページごとにPNGデータを生成する。
swiftc によりコマンドラインからビルドできるのはありがたい。
Xcode 7.0.1 環境で... hello.swift ファイルに
print("hello")
と書いて
$ swiftc -o hello hello.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 などの関連ライブラリも移植されるのだろうか…