【Python tkinter】PDFをCanvasに表示させる方法
2020.05.23 /
Pythonのtkinterを使用してGUIアプリケーションを作成する際、PDFの表示はどのように行えばいいのか。
インターネットで調べてもそれらしい方法は見つけることができなかったので、わたしなりに考えた方法をご紹介します。
もしかしたらもっと簡単で、よりよい方法があるかもしれませんが、一つの方法として覚えていただければと思います。
PDFをCanvasに表示させるには
私が調べたところ、今のところPDFをそのままtkinter上に表示させる方法はありませんでした。
なので少しめんどくさい方法になりますが、PDFを一旦画像ファイル(jpgやpng)に変換して、その後画像ファイルをCanvas上に表示する、という方法を取りたいと思います。
PDFを画像ファイルへの変換は、Pythonのpdf2imageというライブラリを使えば簡単にできます。
pdf2imageは無料なので、有料ソフトを使わずに画像変換ができます。
このPDF→画像の変換ができると、PDFのOCR文字認識や、エクスプローラーのようなPDFプレビューを表示するといったことができるようになります。
PDFを画像に変換(pdf2image)
pdf2imageのインストール
ここではPDFを画像(png)に変換する方法を解説します。
PDFの画像変換にはpdf2imageというライブラリを使用します。以下のようにpipでインストールしてください。
pip install pdf2image
pdf2imageの使用にはPillowという画像処理のライブラリを必要とします。Pillowがインストールされていない場合は、pdf2imageをインストールする際に一緒にインストールされます。
Popplerのダウンロード
pdf2imageはインストールするだけではまだ使えるようになりません。
PopplerというPDFコマンドラインツールをpdf2imageは必要とします。
Popplerは下記サイトからダウンロードすることができます。
*私はWindowsユーザーなのでWindows版をインストールしています
Poppler for Windows
*2020年5月現在、poppler-0.68.0_x86が最新版です。
ダウンロードしたファイルは「7-Zip」などを使って解凍してください。
次にpopplerフォルダをこれから作成するプログラム(pyファイル)と同じ階層に作成し、popplerフォルダ内に解凍したファイル内にある、bin, include, lib, shareのフォルダをコピーしてください。
popplerへの環境変数PATHを付与
Popplerを使うための最後の仕上げとして、Popplerへの環境変数PATHを一時的に付与するコードをpyファイルに記述する必要があります。
# popplerへの環境変数PATHを一時的に付与
poppler_dir = Path(sys.argv[0]).parent.absolute() / "poppler/bin"
os.environ["PATH"] += os.pathsep + str(poppler_dir)
上記コードはPDFの画像変換をする以前に記述する必要があります。
PDFの画像変換(convert_from_path()関数)
pdf2imageのconvert_from_path()関数を使用して、PDFを画像ファイルへ変換します。
パラメータ(引数)にはPDFファイルのパスや解像度(単位:dpi)、ページを指定します。
convert_from_path(パス,解像度,ページ)
解像度は指定しないと200dpiとなります。高くすればより高画質となりますが、その分変換に時間がかかります。私がPDFプレニュー機能で使うときは、100dpiで設定しています。
convert_from_path()関数で作成される画像はPillowライブラリのImage型なのでsave()メソッドを呼び出して保存します。
パラメータには保存先のファイル名、画像形式(”JPEG”,”PNG”等)を指定します。
convert_from_path()関数とsave()メソッドは下記のように使用します。
### PDFをpng画像に変更する ###
path = Path(sys.argv[0]).parent.absolute() / "test.pdf"
pages = convert_from_path(Path(path),200, last_page=1)
pages[0].save(Path(sys.argv[0]).parent.absolute() / "image.png", "png")
上記コードの流れとしては、実行ファイルと同じ階層にあるtest.pdfのパスをpathに格納。
convert_from_path関数に対象PDFのパスが格納されたpathと解像度200、対象ページ(最初の1ページ目)を渡しpagesに格納。
最後に実行ファイルと同じ階層にimage.pngとして変換した画像を保存、という一連の流れとなっています。
画像をCanvasに表示させる
tkinterには、画像を表示するウィジェットとしてcanvasというものがあります。このcanvasウィジェットにPDFをPNGファイルに変換した画像を表示します。
画像を表示させる手順としては、
1: 画像の読み込み
2: キャンパスを作成
3: キャンパスを設置
4: キャンパスに描画
の流れです。以下に各ステップで行うコードを記載します。
# 画像の読み込み #
img = Image.open("image.png")
# キャンバスを作成 #
canvas = tk.Canvas(root, width = img.width, height = img.height, bg="white")
# キャンバスを設置 #
canvas.pack(side="left")
# キャンバスに描画 #
canvas.Photo = ImageTk.PhotoImage(img)
canvas.create_image(0, 0, image=canvas.Photo,anchor=tk.NW)
以上でPDFを画像に変換し、その画像をCanvas上に表示させることができるようになりました。
まとめ
以下にプログラムの全コードを記します。
import tkinter as tk
from PIL import Image, ImageTk
import sys
from pathlib import Path
from pdf2image import convert_from_path
import os
# popplerへの環境変数PATHを一時的に付与
poppler_dir = Path(sys.argv[0]).parent.absolute() / "poppler/bin"
os.environ["PATH"] += os.pathsep + str(poppler_dir)
### PDFをpng画像に変更する ###
path = Path(sys.argv[0]).parent.absolute() / "test.pdf"
pages = convert_from_path(Path(path),100, last_page=1)
pages[0].save(Path(sys.argv[0]).parent.absolute() / "image/image.png", "png")
### GUI設定 ###
# メインウィンドウの設定
root = tk.Tk()
root.title("TkinterのCanvasを使ってみる")
#root.geometry("1000x700")
### キャンバスエリア ###
# 画像の読み込み
img = Image.open("image/image.png")
# キャンバスを作成 #
canvas = tk.Canvas(root, width = img.width, height = img.height, bg="white")
# キャンバスを設置 #
canvas.pack(side="left")
# キャンバスに描画 #
canvas.Photo = ImageTk.PhotoImage(img)
canvas.create_image(0, 0, image=canvas.Photo,anchor=tk.NW)
root.mainloop()