大量のJPGファイルをPDFファイルに変換して結合

スキャニングしてできた大量のJPGファイルを1個のPDFファイルに結合する場合、ImageMagickのconvertを使って

convert *.jpg output.pdf

とすれば簡単に作成できる。
しかしこの方法では、作成時に大量のメモリを消費してしまうのが難点。

私のPC環境で、約180個のJPGファイルを1個のPDFファイルに処理するのに約6分かかった。

処理中、物理メモリを約1GB消費、PF使用量が約1.5GB増加、CPU使用率は20%前後増加といった具合。

処理中、ハードディスクのアクセスランプが点灯しっぱなしになっていたから、使用可能な物理メモリが少なくなれば、もっと時間がかかるかもしれない。

で、あれこれ調べてみたところ、pdftkを使用すれば改善できそうなことがわかった。

pdftkのWindows版は、以下のサイトから入手できる。

pdftk – the pdf toolkit

pdftkを使って大量のJPGファイルをPDFファイルへ変換して、1個のPDFファイルへ結合する手順は、以下の通り。

  1. ImageMagicのconvertを使用して、JPGファイルを1個ずついくつかまとめてPDFファイルへ変換する。
  2. 手順1で作成したPDFファイルを結合する。
  3. 手順1で作成したPDFファイルを削除する。
  4. JPGファイルを削除する。

上記の処理するにあたっては、Perlを使用。ソースコードは、以下の通り。

#!/usr/local/bin/perl
use strict;
use warnings;

my @list = &getFileList;
my @pdf;
my @jpg = @list;
my $tmpPdf = "tmp000";

while (scalar(@jpg) > 0) {
    my $arg = join(" ", splice(@jpg, 0, 20));	#一度に結合するJPGファイルの個数
    &execute("convert $arg $tmpPdf.pdf");
    push(@pdf, "$tmpPdf.pdf");
    $tmpPdf++;
}

my $oldPdf = "";
my $newPdf = "new000";

while (scalar(@pdf) > 0) {
    my $arg = join(" ", splice(@pdf, 0, 20));	#一度に結合するPDFファイルの個数
    &execute("pdftk $oldPdf $arg cat output $newPdf.pdf");	#前回結合したPDFファイル($oldPdf)がある場合は、先頭に追加

    if (length($oldPdf) > 0) {
        unlink($oldPdf);
    }

    $oldPdf = $newPdf . ".pdf";
    $newPdf++;
    unlink split(/\s+/, $arg);
}

&execute("rename $oldPdf output.pdf");
unlink @list;
exit;

sub getFileList {
    open(DIR, "dir *.jpg |");
    my $list = join(" ", sort <DIR>);
    my @list = split(/\s+/, $list);
    close(DIR);

    open(DIR, "dir *.JPG |");
    $list = join(" ", sort <DIR>);
    push(@list, split(/\s+/, $list));
    close(DIR);

    sort @list;
}

sub execute {
    print $_[0], "\n";
    system($_[0]);
}

上記のスクリプトをコマンドプロンプトから実行してみた結果、CPU使用率は増えたものの、物理メモリ消費量とPF使用量についてはほとんど変化は見られず、かなりの改善が見られた。

時間的には、240個のJPGファイルをImageMagickのconvertだけで処理した場合、約3分15秒かかったのが、pdftkを併用した上記のスクリプトで処理した場合だと、約1分15秒となった。

ImageMagickのconvertを使って大量の画像ファイルを1個のPDFファイルにする際に時間がかかっている方は、上記のようにpdftkを併用する方法を一度試してみると良いかもしれない。