PDFをJPEGに変換
概要
PDFファイルの各ページをJPEG画像に変換する。
Linux上でpdftoppmなどのツールを使うことで簡単に変換できるが、フォント周りが若干汚くなったりするため、Mac OS XでPDFKitを使って変換する。
開発環境
- OS: Mac OS X 10.4 (PPC)
- 環境: X-Code
- 言語: Objective-C
変換処理
変換はPDFKitを使って読み込んだPDFファイルから各ページのオブジェクトPDFPageを取得して、以下のように変換していく。
- PDFPageからNSData取得
- NSDataからNSPDFImageRepを生成
- NSPDFImageRepの内容をNSImageに描画
- NSImageからTIFFRepresentationでTIFF表現データを取得
- TIFF表現からNSBitmapImageRepを生成
- NSBitmapImageRepからJPEGデータを生成してファイルへ書き出す
2.でPDFデータを画像に変換する際、NSPDFImageRepではなくNSBitmapImageRepに変換してしまうとこの時点でビットマップデータになってしまうため、この後画像のリサイズをすると画像が荒くなってしまう。NSPDFImageRepであればベクトル情報のままなので、3.でNSImageに変換する際画像をリサイズしても綺麗に処理される。
変換処理部分のソースは以下のとおり。
- (BOOL) _pdf2jpeg:(PDFDocument *)doc path:(NSString *)savePath file:(NSString *)filename { int i; char basename[1024]; char ext[100]; filename2name([filename UTF8String], basename, sizeof(basename)); filename2ext([filename UTF8String], ext, sizeof(ext)); NSDictionary *propJpeg; propJpeg = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithFloat: 0.5], NSImageCompressionFactor, nil]; int pageN = [doc pageCount]; for (i = 0 ; i < pageN ; i++) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; PDFPage *page = [doc pageAtIndex: i]; NSImage *image = [self _pdf2image: page]; if (!image) { [pool release]; return NO; } // Bitmap画像に変換 NSData *tiffRep = [image TIFFRepresentation]; NSBitmapImageRep *imageRep = [[[NSBitmapImageRep alloc] initWithData:tiffRep] autorelease]; if (!imageRep) { [pool release]; return NO; } // Jpeg出力 NSData *dataJpeg; BOOL bResult; dataJpeg = [imageRep representationUsingType: NSJPEGFileType properties:propJpeg]; NSString *filename = [NSString stringWithFormat: @"%s/%s-%d.%s", [savePath UTF8String], basename, i, ext]; bResult = [dataJpeg writeToFile : filename atomically: YES]; if (!bResult) NSLog(@"ERR"); [progressMsg setStringValue:[NSLocalizedString(@"Processing", nil) stringByAppendingFormat:@"...(%d/%d)", i+1, pageN]]; [indicator setDoubleValue:(i + 1)*100 / pageN]; [pool release]; if (needAbort) break; } [progressMsg setStringValue:@""]; return YES; } - (NSImage *)_pdf2image:(PDFPage *)page { NSData *dataPage = [page dataRepresentation]; // PDF画像 (NSBitmapImageRepだとリサイズした時に画像が荒くなる) NSPDFImageRep *pdfImageRep = [[[NSPDFImageRep alloc] initWithData:dataPage] autorelease]; if (!pdfImageRep) return nil; // NSImageに書き込む NSSize size; // 出力サイズ if (0) { // resizeする場合 size.width = 2400; size.height = 2400; } else { size.width = [pdfImageRep pixelsWide]; size.height = [pdfImageRep pixelsHigh]; } NSImage *image = [[[NSImage alloc] initWithSize:size] autorelease]; if (!image) return nil; [image lockFocus]; [pdfImageRep drawInRect: NSMakeRect(0, 0, size.width, size.height)]; [image unlockFocus]; return image; }
全ソースおよびバイナリ
バイナリ:PDF2JPEG.zipソースコード:PDF2JPEG_src.tgz
2008/8/1 更新 V1.2
- 画像サイズを指定できるように修正(等倍のみ)
- Window Close時にプロセスも終了するように修正
2008/7/4 更新 V1.1
- PDFサイズ表示追加
- 変換中のプログレスバー表示追加
- 変換の中断処理追加
2008/6/27 更新 V1.0
- ページ数が多いとメモリを浪費する問題の対策
- 変換中の進捗表示追加
- 変換処理のスレッド化