お題
オタ活に勤しんでいる娘がダウンロードした推しの画像をローソン等でプリントしてポスターやらウチワやら缶バ1やら作るのにいちいち変換してくれるサイト2でPDFに変換しているようです。そんな面倒なことをせずとも前回のように自分のPCだけで完結するやんという話をしましてまた別のコンバータを作ることになりました。
今回はJPG/PNG→PDF変換になります。
尤もわざわざPDFに変換したものをマルチコピー機でPDFプリントしなくても自宅PCからネットワークプリントで先にアップロードだけしておけばいいようなものですが、PDFプリントのA3カラーは80円でネットワークプリントのA3カラーは100円なのです。また、ネットワークプリントではJPGとPDFは印刷可能ですがPNGはダメなようです。
開発環境
- OS:Windows10Home(1903)
- Editor:Visual Studio Code
- Python:3.8.3
調べてみた
「python jpg pdf」でググるとどうやらimg2pdfというライブラリを使えば変換できるらしいので早速導入。
> pip install img2pdf
また、画像を扱うためPIL(Python Imaging Library)も必要なので調達。
> pip install pillow
なぜpillow(枕)なのかは不明。
コード
import sys
import os
import img2pdf
from PIL import Image
def RemoveAlpha(src):
dstPath = os.path.dirname(src)
dstName = os.path.basename(src)
dstPNG = os.path.join(dstPath, "_" + dstName)
img = Image.open(src)
img = img.convert("RGB")
img.save(dstPNG)
return dstPNG
if __name__ == "__main__":
srcOrgImage = sys.argv[1]
print(f"IN:{srcOrgImage}")
srcExt = os.path.splitext(os.path.basename(srcOrgImage))[1]
dstPath = os.path.dirname(srcOrgImage)
dstName = os.path.splitext(os.path.basename(srcOrgImage))[0]
dstPdf = os.path.join(dstPath, f"{dstName}.pdf")
print(f"OUT:{dstPdf}")
if srcExt.upper() == ".PNG":
srcImage = RemoveAlpha(srcOrgImage)
else:
srcImage = srcOrgImage
with open(dstPdf, 'wb') as f:
f.write(img2pdf.convert(srcImage))
if srcOrgImage != srcImage:
os.remove(srcImage)
構想としては前回と同じようにデスクトップ上のショートカットに変換したいファイルをD&Dすると同じフォルダに.pdfを生成するものです。今回もパス周りの処理が延々とあってヤボったいですが。
いくつかの画像ファイルの変換を試していると.jpgでは問題ありませんでしたが.pngファイルの場合にアルファチャンネルを含んでいるPNGはPDFに変換できないとエラーになったのでRemoveAlpha()でRGBA→RGBとして一時ファイルに保存、それを入力ファイルとしてPDF変換させています。
運用
で、今回も起動用のバッチファイルを用意してめでたし。
@echo off
py Image2PDF.py %1
だがしかし・・・
前回の続きになりますがフォルダ名・ファイル名に全角スペースが含まれている場合にD&Dで正しいフルパスが取得できない問題。調べてみると全角スペース以外にもアウト判定な文字があるようです。例えばちょっと細工して
@echo off
py argvTest.py %1 %2 %3 %4 %5 %6 %7 %8 %9
import sys
if __name__ == "__main__":
len = len(sys.argv)
print(f"len={len}")
for i in range(len):
print(sys.argv[i])
これに「C:\Tmp\aaa bbb ccc.txt」(全角スペース入り)を喰わせると
len=3
argvTest.py
C:\Tmp\aaa
bbb
ccc.txt
となるのでぶった切られた文字が全角スペースとわかっているのであればargv[1]以降を最後まで全角スペースを挟んでjoinしてやればなんとかできそうですが、ぶった切られる文字の候補が複数あってしかもその情報はもう失われているので復元は無理かなと。
でもこれが今回のようにバッチファイル経由で動かすPythonではなく.exeのショートカットに対してD&Dすると特にぶった切られることなく一つの文字列として取得できます3。
つまりWindowsのコマンドプロンプト4がイケてない?ですかね。