つきすけ の コーディング記

細かいところで嫌にならないように、小さいことでも解説していくブログ。たまに関係ないことも書く。

Python の Tkinter で 画像をリサイズして表示したりなど

PythonTkinterで、というより、Pillow(PIL)の使い方説明に近くなってしまったが、前回(Python の Tkinter で 画像を表示する - つきすけ の コーディング記)同様Tkinterのバージョンが8.5以前の方のための、PILを用いた画像あれこれ。
そろそろTkinterのバージョンアップデートして仕事したい。

  • Python3.6.1
  • Tkinter8.5


※python2の場合、コード中のtkinterTkinter に変える。

今回は以下の1378 x 2039 という大きい画像を、あの手この手で500 x 500 に収めていく。画像の名前はpictures_name.pngとしておく。

プログラムに使用したサンプルの元画像
使用サンプル画像

普通に表示する

細かいことは前の記事を参照
tsukisuke.hateblo.jp

以下のコードを実行する。下から2行目の第一、第二引数で画像の表示スタート位置(x, y)を指定するため、それぞれ0とすれば、画像左上が表示される。
−10, −20 などにすれば、その分右や真ん中に寄った分が表示される。

import tkinter
from PIL import Image, ImageTk
# --- 基本的な表示準備 ----------------                                         
window = tkinter.Tk()
window.geometry("500x500") # 画面サイズを1000 x 1000 とする                     
window.title("Welcome to the Tkinter")
# 画像を指定                                                                    
img = Image.open('picture_name.png')
img = ImageTk.PhotoImage(img)
# canvasサイズも画面サイズと同じにして描画                              
canvas = tkinter.Canvas(width=500, height=500)
canvas.place(x=0, y=0)
# -------------------------------------                                         
# キャンバスに画像を表示する                                                    
canvas.create_image(0, 0, image=img, anchor=tkinter.NW)
window.mainloop()

500 x 500 にリサイズして表示

縦長の画像ですが、無理やり500 x 500につぶしてしれてやりましょう。
先ほどの基本のコードでpictures_name.pngを指定した行(上記の場合8行目)の直後に次のリサイズ関数を挿入する。
(8行目のImageTk.PhotoImage(img)より前に入れないと、型が変換されてしまいできない)

img = img.resize((500, 500))

こうなる

横幅に合わせてリサイズ

横幅を画面に収めつつ、比率を保って表示し、かつ真ん中を表示する。ということをやる。
さっきのつぶれた書き方をみるだけでできるとは思うが、ここでは元画像のサイズを取得しつつリサイズしてやってみる。

同じく先ほどのコードでpicture_name.pngを指定した行(上記の場合8行目)の直後に画像サイズを取得するため以下を挿入する。

w = img.width # 横幅を取得                                            
h = img.height # 縦幅を取得    

で、その直後にさっきのresize関数を用いて、こうする。
(横方向を500にし、縦方向を同じ縮尺で縮めている。なおinteger型のみ使用可能であるため、若干ずれたりなどする)

img = img.resize(( int(w * (500/w)), int(h * (500/w)) ))

最後に、表示位置を調整。画像の真ん中の方を表示したいため、基本の書き方で下から2行目にあったcanvas.create_image文を次のように変える。
(y座標を、250(キャンバスサイズの半分の値) - 縮尺後の高さ / 2 とすることで、真ん中に持ってきている)

canvas.create_image(0, 250-(h*(500/w)/2), image=img, anchor=tkinter.NW)

こうなる

縦の高さに合わせてリサイズ

横のやつのコードを書き換えればOK
以下、全文

import tkinter
from PIL import Image, ImageTk
# --- 基本的な表示準備 ----------------                                         
window = tkinter.Tk()
window.geometry("500x500") # 画面サイズを1000 x 1000 とする                     
window.title("Welcome to the Tkinter")
# 画像を指定                                                                    
img = Image.open('picture_name.png')
w = img.width # 横幅を取得                                                      
h = img.height # 縦幅を取得                                                     
img = img.resize(( int(w * (500/h)), int(h * (500/h)) ))
img = ImageTk.PhotoImage(img)
# canvasサイズも画面サイズと同じにして描画                                      
canvas = tkinter.Canvas(width=500, height=500)
canvas.place(x=0, y=0)
# -------------------------------------                                         
# キャンバスに画像を表示する                                                    
canvas.create_image(250-(w*(500/h)/2), 0, image=img, anchor=tkinter.NW)
window.mainloop()


最後に

最後の二つ、縦方向と横方向どちらかに合わせて表示する方法のときに、create_image()のanchor引数を変えればできないのかと思ったが、できなかった。
右寄せとか左寄せとかならここだけでできるのでいじってみると良い(詳しく書いてくださっている方のやつをご参照ください(.pachの項) Tkinter 入門: 2. Widget を配置しよう