2023/05/04

【Python】画像ファイルのPDF変換を並列処理で高速化する

これまでに何度も画像ファイルのPDF変換の記事を書いてきたのですが、これまでの変換プログラムの中で最も高速かつ簡単に動作していたのは、「img2pdf」でした。
img2pdfの使い方や速度比較などは、下記の過去記事にて紹介していますのでご参照ください。


これまで記事を作成する中で得られた経験から、concurrent.futuresで並列処理を実装すると、(動かすマシン次第ですが、)処理速度が結構早くなる可能性が見えてきました。
本記事では、並列処理を実装することでimg2pdfの処理速度を超えることを目指した結果をご紹介します。

本記事では、下記の三通りの比較を行います。
  • Method1: img2pdfを使用する
  • Method2: pikepdfとPillowを使用する
  • Method3: Method2をconcurrent.futuresで並列処理
前回までの記事と同様に、書籍をスキャンしたpngファイル(連番ファイル名)群を、pdfに変換することを想定しています。

実行環境は、以下の通りです。
MacBook Air(8コアCPU、10コアGPU、16コアNeural Engine搭載Apple M2チップ, 16GBメモリ)
------
Python 3.10.10
img2pdf 0.4.4
pikepdf 7.1.1
Pillow 9.3.0

Method1 : img2pdfを使う


Method2: pikepdfとPillowを使用する


Method3: Method2をconcurrent.futuresで並列処理

ライブラリとして、下記のようにpic2pdfという名前で整理しました。
一部の関数はimg2pdfのように動かせます。

10個の異なるpng画像ファイル群での出力ファイルサイズと実行時間の比較は、以下の通りです。


まとめ

今回作成したMethod2やMethod3による出力は、img2pdfで作成したPDFと完全に同じサイズのPDFにはなりませんでした。 img2pdfはロスレスらしいので、今回作成したものとは異なる処理でロスレスを実現しているみたいです。
なので、Method2やMethod3による出力はロスレスではなく、注意が必要です。

Method2は、img2pdfのソースコード(4000行超)と比較すればかなりシンプルに書くことができましたが、変換処理に2~3倍時間がかかっています。
それをconcurrent.futuresで並列処理を実装して、力技で高速化したのがMethod3です。あくまで、私の環境での計測結果になりますが、Method2よりも5倍以上早くなっています。
結果的に、img2pdfと比較して、半分程度で処理されるようになりました。また、プログレスバーを実装したので、処理時間が長い場合でも処理が動いていることが分かるようになりました。

今後も改良を重ねて、行こうと考えているので気になる方はGithubの方をチェックして下さい。

下記のようなPDF変換用のプログラムも作成していますので、今回の成果は、こちらで使用しようと考えています。