LoginSignup
5
4

More than 1 year has passed since last update.

複数フォルダ内の画像をそれぞれフォルダごとに別々のpdfに一括で変換する

Last updated at Posted at 2021-01-08

はじめに

フォルダごとに分けた大量の画像があるのですが、簡単に取り扱えるようにフォルダごとのPDFファイルに変換しようと思いました。
最初は、Adobeを使ったり、cubePDFを使ったりしたのですが、どちらも実行速度が遅いという問題がありました。そのため、Pythonでプログラムを作ることにしました。
プログラムを調べたところ、以下のプログラムが見つかりました。

高速で、ロスレスでPDFに変換できるimg2pdfというライブラリを使用してます。
基本的にはこれをベースに、少し使いにくかった部分を変更しました。

できること

こんなフォルダがあったときに、

画像まとめ
├── 2015
│   ├── img1.jpg
│   ├── img2.jpg
│   ├── img3.jpg
├── 2016
│   ├── img10.jpg
│   ├── img11.jpg
│   ├── img12.jpg
├── 2017
│   ├── img21.jpg
│   ├── img22.jpg
│   ├── img23.jpg


画像まとめという親フォルダをドラッグアンドドロップすることで、以下のように子フォルダ名を使用したPDFファイルに変換することができます。

画像まとめ
├── 2015
│   ├── img1.jpg
│   ├── img2.jpg
│   ├── img3.jpg
├── 2016
│   ├── img10.jpg
│   ├── img11.jpg
│   ├── img12.jpg
├── 2017
│   ├── img21.jpg
│   ├── img22.jpg
│   ├── img23.jpg
├── 2015.pdf
├── 2016.pdf
├── 2017.pdf

ライブラリのインポート

pip install img2pdf

コード

make_pdf.py
import img2pdf
from pathlib import Path
import re


#数字がない文字列は前に持ってきている。
#逆にしたいときは代2引数にfloat('inf')を指定
#https://note.nkmk.me/python-sort-num-str/
def extract_num(s, ret=0):
    p = re.compile(r'(\d+)')    
    search = p.search(s)
    if search:
        return int(search.groups()[-1])
        print(search.groups())
    else:
        return ret


#単処理
def ImageToPdf(outputpath, imagepath):
    '''
    outputpath: pathlib.Path()
    imagepath: pathlib.Path()
    '''
    lists = list(imagepath.glob("**/*"))#単フォルダ内を検索
    #jpg,pngファイルだけpdfに結合
    #Pathlib.WindowsPath()をstring型に変換しないとエラー
    #jpegにも対応
    imgpath_list = [str(i) for i in lists if i.match("*.jpg") or i.match("*.png") or i.match("*.jpeg")]

    #https://note.nkmk.me/python-sort-num-str/
    #0埋めされていない番号順に対応
    imgpath_list.sort(key=lambda s: extract_num(s))

    #pdfを作成
    with open(outputpath,"wb") as f:
        f.write(img2pdf.convert(imgpath_list))
    print(outputpath.name + " :Done")

#複数フォルダをループ処理する
while True:
    #作業フォルダ
    base_path = input("PDFに変換したいファルダが入った親フォルダをd&Pしてください")
    base_path = base_path.strip(" \' ")
    #作業フォルダ内のディレクトリだけを抽出する
    glob = Path(base_path).glob("*")
    imagefolderlist = list([item for item in list(glob) if item.is_dir()])
    #outputpathに指定ディレクトリと同名を指定する
    outputpathlist = list([item.with_name(item.name + ".pdf") for item in imagefolderlist])
    #ループ処理を行う
    for outputpath,imagepath in zip(outputpathlist,imagefolderlist):
        try:
            ImageToPdf(outputpath,imagepath)
        except:
            import traceback
            traceback.print_exc()

変更点

こちらのプログラムとの変更点は、
・パスをプログラム内に書かなければいけなかったところを、フォルダをドラックアンドドロップしてどんどん変換できるようにしました。
.jpegの拡張子に対応していなかったので対応させました。
・エラー内容を表示させるようにしました。
・0埋めされていないファイルも番号順に並べるようにしました。例えば、{1, 2, 10}を並べ替えると、{1,10,2}となってしまい、本来回避するためには、{01, 02, 10}と0で埋めないといけないです。なお、番号がないファイルは前に持ってこられます。

ライブラリのアップデートによって改善されたこと

以前はアルファチャンネルを含むPNG画像は変換できずにエラーになっていました。
しかし2021/8/22のアップデートで、ソフトマスクを使用してアルファチャンネルのデータを保ったままPDFに変換できるようになりました。

まとめ

フォルダで分けられた画像を、pdfに一気に変換するときに便利です。
ぜひ使ってください。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4