無料Wikiサービス | デモページ
Linuxなどのメモ書き
検索

Adsense

PDFをJPEGに変換 の差分
Rev.6→最新版  追加箇所 削除箇所


概要

PDFファイルの各ページをJPEG画像に変換する。

Linux上でpdftoppmなどのツールを使うことで簡単に変換できるが、フォント周りが若干汚くなったりするため、Mac OS XでPDFKitを使って変換する。

開発環境

  • OS: Mac OS X 10.4 (PPC)
  • 環境: X-Code
  • 言語: Objective-C

変換処理

変換はPDFKitを使って読み込んだPDFファイルから各ページのオブジェクトPDFPageを取得して、以下のように変換していく。

  1. PDFPageからNSData取得
  2. NSDataからNSPDFImageRepを生成
  3. NSPDFImageRepの内容をNSImageに描画
  4. NSImageからTIFFRepresentationでTIFF表現データを取得
  5. TIFF表現からNSBitmapImageRepを生成
  6. 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];

	// docはPDFDocumentオブジェクト
	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];

		// Bitmap画像に変換
		NSData *tiffRep = [image TIFFRepresentation];
		NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:tiffRep];
		if (!imageRep) {
			[image 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");

		[textMsg setStringValue:[NSLocalizedString(@"Processing", nil)
				stringByAppendingFormat:@"...(%d/%d)", i+1, pageN]];

		[image release];
		[imageRep release];
		[pool release];
	}

	[textMsg setStringValue:@""];

	return YES;
}

- (NSImage *)_pdf2image:(PDFPage *)page
{
	NSData *dataPage = [page dataRepresentation];

	// PDF画像 (NSBitmapImageRepだとリサイズした時に画像が荒くなる)
	NSPDFImageRep *pdfImageRep = [[NSPDFImageRep alloc] initWithData:dataPage];

	// 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];
	[image lockFocus];
	[pdfImageRep drawInRect: NSMakeRect(0, 0, size.width, size.height)];
	[image unlockFocus];

	[pdfImageRep release];

	return image;
}


全ソースおよびバイナリ

バイナリ:PDF2JPEG.zip
ソースコード:PDF2JPEG_src.tgz

TODO:適当すぎるユーザインタフェース6/27 更新  V1.0


  • ページ数が多いとメモリを浪費する問題の対策
  • 変換中の進捗表示追加
  • 変換処理のスレッド化

TODO:
画像サイズの指定
中断ボタン