How to combine jpeg files to a PDF

iPhoneにGoodReaderというPDFを高速に表示できるアプリがある。PDF以外も対応しているのだけど、試してみたことがないのでその機能がどれぐらいかと言うことは分からない。ただ、PDFの表示速度だけでこのソフトを選んでも良いんじゃないかと思わせるぐらい、速い。

iPhoneというか、OSXはもともとネイティブにPDFに対応している。その前の歴史としてNeXT Stepの表示システムがdisplay postscriptだったという由来があるのだけど、歴史は置いておいて、その流れをくむiPhoneのアプリケーションフレームワークであるCocoa TouchもPDFを投げれば表示してくれるような仕組みがある。ただし遅い。

GoodReaderはPDFをレンダリングするコードを独自に(オリジナルかどうかは分からないけど)実装して高速化しているようだ。

ここまでが実は話の枕であり、いままでPDFの文書をiPhoneで移動中に読みたいと思うことがあっても、その遅さにげんなりして、どうも積極的に読もうという気にはならなかった。

Jpegにして画像として見ると幾分ましだというのはあったけれども、今度はそういう用途としての画像ビューアでしっくりくるアプリを見つけられなかった。

PDFに関して、GoodReaderの登場ですっきり解決なのだけど、そうも行かないもう一つの事情もあった。スキャンしてjpegで保存している資料、そういうのをまとめてPDFにして、いざとなればiPhoneで閲覧できるようにしておきたかったのだ。

ScanSnapなどの文明の利器があれば簡単に実現可能なようだが、我が家には残念ながらない。ないならないでどうにかしたい。つまり、どうにかしようぜ、という話なのだ。

以下はMacOSXである程度プログラミングができると言うことを前提に書いてあると言うことをあらかじめ断っておかないといけないかもしれない。

OSXは前述の通りPDFをネイティブに扱えるので、なにか簡単にできる方法はないかと調べてみたら、やはりできるらしいと言うことが分かった。

PDFDocumentなるクラスがあり、

PDFDocument *document = [[[PDFDocument alloc] init] autorelease];

等とインスタンスを生成して、それに各ページを足していけばいいようだ。

[document insertPage:page atIndex:index];

insertとあるが、現在のページ数でinsertしていけばどんどん後に足されていく。

PDF関係のクラスはQuartz関係のクラスで頭にNSがつかないのでざっとクラスリストを見るときに見落としそうになった。NSはNeXT Stepの略ですね。

Jpegファイルを読み込むのも簡単で

NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];

とすれば、previewで表示可能なものは読み込める。PDFPageクラスにも便利なメソッドがあり、生成時に

PDFPage *page = [[PDFPage alloc] initWithImage:image];

とすればその画像を含んだページを作ってくれる。

ここまでくれば、後は以上を組み合わせれば完成だ。

#import <Foundation/Foundation.h>
#import <Quartz/Quartz.h>
#import <AppKit/AppKit.h>
int main (int argc, const char * argv[]) {
if (argc < 2)
return -1;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *path = [NSString stringWithCString:argv[1] encoding:NSUTF8StringEncoding];
NSString *output;
if (argc < 3)
output = [[[NSString stringWithString:@"~/Desktop"] stringByExpandingTildeInPath]
stringByAppendingPathComponent:[[path lastPathComponent] stringByAppendingPathExtension:@"pdf"]];
else
output = [NSString stringWithCString:argv[2] encoding:NSUTF8StringEncoding];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *files = [fileManager directoryContentsAtPath:path];
if (files)
{
PDFDocument *document = [[[PDFDocument alloc] init] autorelease];
int i = 0;
for (NSString *filename in files)
{
if ([[filename pathExtension] isEqualToString:@"jpg"])
{
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[path stringByAppendingPathComponent:filename]];
if (image)
{
PDFPage *page = [[PDFPage alloc] initWithImage:image];
[document insertPage:page atIndex:i++];
[page release];
}
[image release];
}
}
[document writeToFile:output];
}
[pool drain];
return 0;
}