画像を一冊のファイルにまとめたい、今回はそんな画像をまとめてPDFを作成したときのメモです。
もくじ:
はじめに
画像からPDFへの変換にはサードパーティ製のimg2pdf
モジュールが手軽で便利です。今回の目的にはimg2pdf.convert()
一発です。
モジュールがインストールされていない場合はpipで導入できます。PillowやPDFリーダ・ライタなど依存モジュールも自動的に入ります。
1 | > pip install img2pdf |
1. 画像ファイルをPDFに変換する
基本的にはimg2pdf.convert()
の返す値をバイナリモードでファイルに書き込めばOK。
img2pdf.convert()
の引数としては画像ファイルのパス文字列(str
)や、それらパス文字列のリストの他、ファイルなどのストリームを受け付けるようです。
今回は指定したディレクトリにある画像ファイルを一括して、単一のPDFにまとめる処理をやりたいので、パスのリストを渡します。
1.1 画像ファイルパスの取得
img2pdfはJPEGやPNG(ただしアルファチャネルなし)を読めるようですので、指定されたディレクトリの直下にあるファイルの拡張子を調べてパスのリスト(サンプルではimages_
)を作ります。
直下だけでなく階層を辿ってリストを作成したい場合にはos.walk()
やglob
モジュールを使って下さい。
1 2 3 4 5 6 7 | images_ = [] for item in os.listdir(dir_path): path_ = os.path.join(dir_path, item) if os.path.isfile(path_): ext_ = os.path.splitext(path_)[-1].lower() if ext_ in [".jpg", ".jpeg", ".png"]: images_.append(path_) |
また、出力されるPDFデータは対象のディレクトリと同じ階層に同名のファイル名を付けて保存することにします。
1.2 出力の調整
特に指定しなければ、img2pdfは入力された画像データのサイズなどそのまま出力しようとしますが、明示的に指定することもできます。
ページのサイズを明示的に指定するには、layout_fun
を指定します。具体的にはimg2pdf
モジュールにあるget_layout_fun()
関数を使います。
1 2 | def get_layout_fun( pagesize=None, imgsize=None, border=None, fit=None, auto_orient=False): |
ここではmm(ミリメートル)をポイントに換算してpagesize
を指定します。
1 | pagesize_ = (img2pdf.mm_to_pt(182), img2pdf.mm_to_pt(257)) |
2. サンプル
今回のサンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | # -*- coding: utf-8 -*- import os import img2pdf from traceback import print_exc class params_: # B5 pagesize_ = (img2pdf.mm_to_pt(182), img2pdf.mm_to_pt(257)) def convert_dir(dir_path): # check input argument if os.path.isdir(dir_path): pdf_file_path = "{}.pdf".format(os.path.basename(dir_path)) pdf_file_path = os.path.join(os.path.dirname(dir_path), pdf_file_path) else: raise Exception("invalid path") # listing image files images_ = [] print("scanning directory: {}".format(dir_path)) for item in os.listdir(dir_path): path_ = os.path.join(dir_path, item) if os.path.isfile(path_): ext_ = os.path.splitext(path_)[-1].lower() if ext_ in [".jpg", ".jpeg", ".png"]: images_.append(path_) else: # skip non-image file continue else: # skip sub directory continue if len(images_) == 0: raise Exception("no image files") else: images_.sort() layout_ = img2pdf.get_layout_fun(params_.pagesize_) print("generating pdf file:{} ...".format(pdf_file_path)) with open(pdf_file_path, 'wb') as f: f.write(img2pdf.convert(images_, layout_fun=layout_)) if __name__ == "__main__": try: dir_path = "./path/to/images_dir" convert_dir(dir_path) except BaseException: print_exc() |
おわり。