以前も、複数画像をPDFに変換する方法に関して、img2pdfの紹介記事を書いたのですが、img2pdfやそれ以外の手法での実行時間やファイルサイズなどを比較してみました。
本記事では、img2pdfを用いてpdfにする方法と、reportlabとPillowを組み合わせる方法、Pillowのみを使う方法の三種類を比較した結果を紹介します。
実行時間は、実行環境などで変わるため、あくまで目安です。計測に関しても、Jupyter Lab上で、実行した結果であり、複数回測って平均をとるというような厳密なことはしておりません。
実行環境は、以下の通りです。
MacBook Pro 13-inch (2017)
------
Python 3.8.11
img2pdf 0.4.1
reportlab 3.3.0
Pillow 8.1.0
下記のスクリプトは、いずれも書籍をスキャンしたpngファイル(連番ファイル名)を、pdfに変換することを想定しています。
Method1 : img2pdfを使う
Method2 : reportlabとPillowを組み合わせる
Method3 : Pillowだけを使う
10個の異なるpng画像ファイル群での実行時間と出力ファイルサイズの比較は、以下の通りです。
![]() |
![]() |
img2pdfを用いた方法は、実行時間(変換にかかる時間)が特に短いです。 出力されたpdfファイルサイズは、pngファイルの合計サイズよりとほぼ同じサイズになっており、pngファイルを複雑に処理していないことが伺われます。 img2pdfに関して、残念なのはアルファチャンネルのある透過pngに対応していない点です。事前に処理しておいてね、という仕様となっています。
reportlabとPillowを組み合わせる方法ですが、実行時間が特に長く、画像のみのpdfを作るのであれば、reportlabを組み合わせる必要はないかなと感じました。
Pillowだけを用いる方法は、入力ファイルによって結果がばらついていますが、基本的にはファイルサイズが圧縮されています。リサンプリングしているため実行時間が伸びますが、この方法では、qualityの値を調整することでファイルサイズをさらに圧縮することも可能なので、ファイルサイズを調整したい時には良い方法だと思います。
ただし、img2pdfのように、見開きの設定など複雑なことはできないようなので、割り切って使うか他のツールと組み合わせる必要があります。
追記:2022/12/09
PyMuPDFを使って、変換する方法が分かったので追加しました。実行速度などは測っていません。
Method4 : PyMuPDFを使う
import os | |
import fitz | |
file_dir = '(画像ファイルが入っているフォルダのパス)' | |
file_ext = '.png' | |
img_files = sorted([os.path.join(file_dir, _) for _ in os.listdir(file_dir) if _.endswith(file_ext)]) | |
# PDFの新規作成 | |
doc = fitz.open() | |
# PDFにPNG画像を書き込む | |
for file in img_files: | |
# 画像を読み込む | |
with fitz.open(file) as img: | |
rect = img[0].rect | |
pdfbytes = img.convert_to_pdf() | |
# 新しいページを追加 | |
page = doc.new_page(width=rect.width, height=rect.height) | |
page.show_pdf_page(rect, fitz.open('pdf', pdfbytes), 0) | |
# PDFを保存 | |
doc.save('output4.pdf') |
Recipes: Images — PyMuPDF 1.21.0 documentation
Method5 : borbを使う
import os | |
import borb | |
from PIL import Image | |
file_dir = '(画像ファイルが入っているフォルダのパス)' | |
file_ext = '.png' | |
img_files = sorted([os.path.join(file_dir, _) for _ in os.listdir(file_dir) if _.endswith(file_ext)]) | |
doc = borb.pdf.Document() | |
for file in img_files: | |
img = Image.open(file) | |
page = borb.pdf.Page(width=img.width, height=img.height) | |
doc.add_page(page) | |
page_layout = borb.pdf.SingleColumnLayoutWithOverflow(page, horizontal_margin=0, vertical_margin=0) | |
page_layout.add(borb.pdf.Image(img, width=img.width, height=img.height, margin_bottom=0, margin_left=0, margin_right=0, margin_top=0, border_width=0)) | |
with open('output5.pdf', 'wb') as pdf_file_handle: | |
borb.pdf.PDF.dumps(pdf_file_handle, doc) |
続き
【Python】画像のみの固定レイアウトのePubをPDFに変換する
【Python】複数枚のPNG画像をJPEGに圧縮してPDFに変換する