Tex, python, illusrator, VPSの学生ノート

latotex-blog

Python

JPEGのファイルを1つのPDFにまとめ印刷するまで自動化する!

投稿日:2020年9月8日 更新日:







オンライン講義で、講義前に使用する本のページをすべて写真で送ってくる先生がいます。
3ページぐらいであれば良いですが、10ページ以上になると印刷が面倒くさいと感じてしまいます。
そこで、1つのPDFにまとめ印刷するまで自動化することにしました。

以下、使用した環境・ライブラリです。

Python:3.7.7
img2pdf:0.3.6
PyPDF2:1.26.0
Pillow:7.1.2
pywinauto:0.6.8
Selenium:3.141.0

スポンサーリンク

Pythonコード

image_folderとprint_pdfがコマンド引数です。print_pdfは1のとき印刷、1以外は印刷しないというように設定してあります。(デフォルトは0)

image_to_pdf_and_print.py --image_folder=<画像フォルダーのパス> [--print_pdf=<印刷するときは1>]

という感じで数字とフォルダーパスを指定してください。

#!/usr/bin/env python3
"""image_to_pdf_and_print.py

Usage:
    image_to_pdf_and_print.py --image_folder= [--print_pdf=<0_or_1>]
    image_to_pdf_and_print.py -h | --help
Options:
    -h --help show this screen and exit.
    --image_folder= The path to the image folder.
    --print_pdf=<0_or_1> Print or not [default: 0].
"""



#必要なものを宣言
import os
import glob
import pathlib
import img2pdf
import PyPDF2
from PIL import Image
from docopt import docopt

#印刷処理に関するライブラリ宣言
import pywinauto
from selenium import webdriver
import time
import chromedriver_binary


#pdfをまとめて1つにする
def pdf_merger(out_pdf, pdfs):
    merger = PyPDF2.PdfFileMerger()

    for pdf in pdfs:
        merger.append(pdf)

    merger.write(out_pdf)
    merger.close()

#印刷の自動化
def print_dialog():
    pywinauto.keyboard.send_keys("+^P")
    a_check = lambda:pywinauto.findwindows.find_windows(title=u'印刷')[0]
    dialog = pywinauto.timings.wait_until_passes(5, 1, a_check)

    pwa_app = pywinauto.Application()
    pwa_app.connect(handle=dialog)

    window = pwa_app[u'印刷']
    window.wait('ready')
    pywinauto.keyboard.send_keys("%P")

#PDFに変換
def convert_to_PDF(f, file1, out_file):

    #PNGをJPGに変換
    def PNGtoJPG(input_file, file_jpeg):
        input_im = Image.open(input_file)
        rgb_im = input_im.convert('RGB')
        rgb_im.save(file_jpeg)

    #JPGをPDFに変換
    def JPGtoPDF(jpeg_file, file_pdf):

        input_im = Image.open(jpeg_file)
        width, height = input_im.size

        #JPGが横長の場合、縦長に直す作業をする
        if width > height:
            imput_im = input_im.rotate(-90, expand = True)
            imput_im.save(f)

        cov_pdf = img2pdf.convert(f)
        file = open(file_pdf , "wb")
        file.write(cov_pdf)

    #JPEGのファイル拡張子は3種あるので、リストにする
    image_file_formats = ['.jpg', '.jpe', '.jpeg']

    #ファイルがPNG形式の場合
    if input_file.suffix == '.png':
        file_jpeg = file1.joinpath(f.replace(input_file.suffix, '.jpeg'))
        PNGtoJPG(f, file_jpeg)
        file_pdf = file1.joinpath(f.replace(input_file.suffix, '.pdf'))
        JPGtoPDF(file_jpeg, file_pdf)
        pdfs.append(str(file_pdf))

    #ファイルがJPEG形式の場合
    elif input_file.suffix in image_file_formats:
        file_pdf = file1.joinpath(f.replace(input_file.suffix, '.pdf'))
        JPGtoPDF(f, file_pdf)
        pdfs.append(str(file_pdf))

    else:
        pass


    #PDFの変換が終わったら、結合に入る
    pdf_merger(out_file, pdfs)


if __name__ == '__main__':

    args = docopt(__doc__)
    image_folder = args['--image_folder']
    print_pdf = args['--print_pdf']


    #変換したPDFファイル・結合したPDFファイルを入れるサブフォルダー
    sub_name = 'box'
    file0 =  pathlib.Path(image_folder)
    file1 = file0.joinpath(sub_name)
    out_file = str(pathlib.Path(file1).joinpath('out.pdf'))

    #サブフォルダーを作成
    os.makedirs(file1, exist_ok=True)
    os.chdir(image_folder)

    pdfs = []
    files = glob.glob('*')

    for f in files:
        input_file = file0.joinpath(f)
        convert_to_PDF(f, file1, out_file)


    #'--print_pdf'を1にした場合、印刷が行われるようにする
    if print_pdf == 1:
        driver = webdriver.Chrome()
        driver.get(out_file)
        time.sleep(5)

        #印刷処理
        print_dialog()

        time.sleep(5)

        driver.quit()
    else:
        pass

上手くいかなかったところ

両面印刷やカラー指定まで自動化できなかったのが惜しいところです。まあ、1つにまとめたPDFができてしまえば、印刷設定は1度で済むのですが・・・・
ダイアログの要素は、print(pwa_app.YourDialog.print_control_identifiers())

#pwa_appとwindowはprint_dialogで定義したものと同じ
  print(pwa_app.YourDialog.print_control_identifiers())

  detailed_setting = window.child_window(title="詳細設定(&R)", class_name="Button")
  if detailed_setting.is_enabled():
      detailed_setting.click()

で一覧をみることができ、child_window()指定することで取得できます。上のプログラムでは、印刷ダイアログを開く→「詳細設定(R)」のボタンを押すまでの動作を自動化しています。両面印刷は「詳細設定(R)」のボタンを押す→「用紙/品質」のタブを押す→「両面印刷(B)」から両面印刷を選ぶというプロセスが必要ですが、「詳細設定(R)」のボタンよりも深い層についてchild_window()が用意されていないため両面印刷ができませんでした。進展があればまたお伝えします。

ちなみに、PowerPointやExcel、Wordの文書も1つのPDFに変換できます!
以下のリンクからどうぞ。

お世話になったサイト様

pywinautoを使った印刷の自動化
https://ohtorii.hatenadiary.jp/entry/20171029/p1

JPEGからPDFへの変換方法
https://kimamani89.com/2019/05/06/post-475/


-Python
-, , ,

Copyright© latotex-blog , 2020 All Rights Reserved Powered by STINGER.