このページでは、Tkinter で画像を扱う方法について解説していきたいと思います。
Contents
画像の使いどころ
Tkinter で画像を使うことにより、アプリ上に画像を表示することができます。
GUI アプリに簡単に画像を表示できることが、Tkinter で画像を扱う最大のメリットです。
例えば画像処理アプリなんかも簡単に作成することができます。
ただし、Tkinter 自体にも画像処理機能は備えられていますが、制限が多いためあまり画像処理には向きません。
なので、画像処理自体は Pillow や OpenCV 等の画像処理が得意なライブラリで行う方が良いと思います。
といっても、GUI アプリ上に画像処理後の画像を表示するためには、結局 Tkinter での画像の扱い方をしっかり理解しておく必要があります。
画像の扱い方
Tkinter では、画像を扱うためのクラスが2つ用意されています。
PhotoImage
クラスBitmapImage
クラス
2つ用意されているのですが、使うのはほぼ前者の PhotoImage
クラスになると思います。
BitmapImage
クラスで扱えるのは XBM という形式の2値画像(白黒画像)のみです。
カラーの画像や写真画像を扱うのであれば、迷わず PhotoImage
クラスを選択しましょう。
スポンサーリンク
PhotoImage
クラスで画像を扱う
ここからは実際に Tkinter で画像を扱う方法について解説していきます。
まずは PhotoImage
クラスでの画像の扱い方について解説していきます。
PhotoImage
クラスでの基本的な画像の扱い方
PhotoImage
クラスでは下記のフォーマットの画像を扱うことが可能です。
- PGM
- PPM
- GIF
- PNG
最後の PNG は Tkinter のバージョン 8.6 からサポートされているようです。
上記のフォーマットの「画像ファイルを読み込んで表示」するというのが、Tkinter の PhotoImage
クラスでの最も基本的な画像の扱い方だと思います。
下のスクリプトは、PhotoImage
クラスでアプリ上に画像を表示する簡単な例になります。
# -*- coding:utf-8 -*-
# 1. tkinterをインポート
import tkinter
# 2. メインウインドウを作成
app = tkinter.Tk()
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="gif_neko.gif",
)
# 4. PhotoImageオブジェクトの表示
label = tkinter.Label(
app,
image=photo
)
label.pack()
# 5. メインループ
app.mainloop()
上記スクリプトのコメントにも書いている通り、PhotoImage
クラスで画像を扱う基本的な流れは次のようになります。
- tkinter をインポート
- メインウィンドウを作成
PhotoImage
オブジェクトの作成PhotoImage
オブジェクトの表示- メインループ
1. と 2. と 5. は PhotoImage
クラスで画像を表示するための準備みたいなものです。これらを行わないと PhotoImage
クラスのオブジェクトを生成したり、オブジェクトを表示したりすることができません。
特に 2. を行わないと PhotoImage
クラスのオブジェクトの生成もできないので注意しましょう!
3. の「PhotoImage
オブジェクトの作成」を行うことで画像を読み込み、さらに 4. の「PhotoImage
オブジェクトの表示」を行うことでその画像をアプリ上に表示することができます。
4. の「PhotoImage
オブジェクトの表示」は、上記スクリプトでは Label の中に表示していますが、他のウィジェット(Canvas や Button)の中に表示しても OK です。
例えば Button であれば、上記の Label 同様にコンストラクタや configure
メソッドで image
キーワードに PhotoImage
オブジェクトを指定することにより画像を表示することが可能です。
また、Canvas であれば、create_image
メソッドから画像を表示することができます。
3. の「PhotoImage
オブジェクトの作成」では PhotoImage
クラスのコンストラクタに file
キーワードを指定することで、指定したファイルを読み込んでいますが、他にも様々なキーワードを指定して画像の設定を行うことが可能です。
また PhotoImage
クラスのコンストラクタで生成したオブジェクトに対して様々なメソッドが用意されており、これらのメソッドを用いて簡単な画像処理も行うことが可能です。
ここからは、まず PhotoImage
コンストラクタへのキーワード指定による設定について解説し、その次に PhotoImage
コンストラクタで生成したオブジェクトに対するメソッド(操作)について解説していきたいと思います。
PhotoImage
クラスの設定
コンストラクタにキーワード指定形式で生成するオブジェクトの設定行うことが可能です。
どのようなキーワードが指定できるかについて解説していきます。
file
file
キーワードでファイル名を指定することで、読み込む画像ファイルを設定することができます。
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.pgm"
)
data
また、data
キーワードでデータのリストを指定すれば、ファイルからではなく画像データを読み込んで画像オブジェクトを生成することができます。
data
で指定する画像データも下記の画像フォーマットである必要があります。
- PGM
- PPM
- GIF
- PNG
data
で画像データを読み込んで表示するサンプルスクリプトは下記のようになります。
要はファイルから読み込んだデータをdata
に指定すれば良いです。
# -*- coding:utf-8 -*-
# 1. tkinterをインポート
import tkinter
# 2. メインウインドウを作成
app = tkinter.Tk()
# 3. PhotoImageオブジェクトの作成
# ファイルの読み込み
f = open("cute_cat.png", "rb")
data = f.read()
f.close()
photo = tkinter.PhotoImage(
data=data,
)
# 4. PhotoImageオブジェクトの表示
label = tkinter.Label(
app,
image=photo
)
label.pack()
# 5. メインループ
app.mainloop()
width
・height
width
と height
の指定により画像を読み込むサイズを指定できます。
ただし、どの位置から読み込むからは指定することはできず、画像の左上から width
と height
で指定したサイズ分が読み込まれることになります。
例えば下記のサンプルスクリプトでは画像全体が表示されますが、
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.pgm"
)
下記のように width
と height
を指定することで画像の左上から 200
x 200
px 分のみが表示されるようになります。
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.pgm",
width=200,
height=200
)
width
と height
が画像サイズを超える場合でも指定した width
と height
分の画像として扱われます。ただし画像サイズ超えた部分は透明のピクセルとして表示されます(つまり背景がそのまま表示される)。
format
format
ではどのフォーマットの画像を読み込むかを設定することができます。
指定できる format
は下記の3つになります。
"ppm"
"gif"
"png"
"pgm"
は指定できませんので、PGM ファイルの時は "ppm"
を指定します。
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.pgm"
format="ppm"
)
ただし基本的に読み込むファイルの拡張子や画像データのヘッダーから自動的に画像のフォーマットは設定されるようですので、無理に format
を指定する必要はないと思います。
gamma
gamma
を浮動小数点の値を指定することで画像に対してガンマ補正を行うことができるようです。
ただし私の環境では動作してくれませんでした…。
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.pgm"
gamma=0.5
)
palette
palette
を指定することで画像の簡単な色変換行うことができるようです。
ただし私の環境では動作してくれませんでした…。
下記のように palette
に1つの数字を指定すれば、グレースケール画像に色変換され、
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.png",
palette="256"
)
下記のように palette
に “/
” (スラッシュ)で区切って赤・緑・青の3つ色数を指定すれば、元々の画像の色数(例えば赤・緑・青それぞれ256色)を指定した色数で表現するように色変換されるようです。
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.png",
palette="7/7/4"
)
実際に動作させられなかった部分は仕様書やソースコードを読んだ結果を解説として記述しています
もし動作させ方が分かった場合は追記します
スポンサーリンク
PhotoImage
クラスのメソッド
次は PhotoImage
クラスのオブジェクトで実行できるメソッドについて解説していきます。
特に subsample
や zoom
に関しては下記ページで、
put
・get
・transparency_set
・transparency_get
では下記ページで実際の利用例を紹介していますので、こちらも合わせてお読みいただければと思います。
width
・height
width
と height
は実行したオブジェクトの画像の幅・高さを取得するメソッドです。
# photoはPhotoImageのオブジェクト
width = photo.width()
height = photo.height()
コンストラクタで width
や height
を指定した場合は、width()
と height()
実行時にはその指定した値が返却されます。
type
type
はそのオブジェクトの画像タイプを取得するメソッドです。
取得できる具体的なタイプは下記の二つになります。
"photo"
"bitmap"
# photoはPhotoImageのオブジェクト
photo.type()
PhotoImage
クラスのオブジェクトであれば、必ず "photo"
が返却されるはずです。
configure
configure
はコンストラクタ実行時に指定した画像オブジェクトの設定を変更するメソッドです。
指定できるキーワードは PhotoImage
クラスの設定で紹介したものになります。
下記が configure
メソッドの使用例です。
画像を表示するラベルをクリックされた際に click_func
関数が実行され、その中で configure()
メソッド実行されます。
さらに configure
で file
を指定していますので、ラベルクリックすると表示する画像が変化することになります("neko.pgm"
から "cute_cat.png"
に変化)。
# -*- coding:utf-8 -*-
# ラベルクリック時の処理
def click_func(event):
global photo
# 画像ファイルを再設定
photo.config(
file="cute_cat.png"
)
# 1. tkinterをインポート
import tkinter
# 2. メインウインドウを作成
app = tkinter.Tk()
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.pgm",
)
print(photo.type())
print(photo.height())
# 4. PhotoImageオブジェクトの表示
label = tkinter.Label(
app,
image=photo
)
label.pack()
# ラベルクリック時のイベント受付を設定
label.bind("<ButtonPress>", click_func)
# 5. メインループ
app.mainloop()
blank
blank
は実行したオブジェクトの画像全体を透明にするメソッドです。
下記のサンプルスクリプトでは画像を表示するラベルをクリックすると、blank
メソッドが実行されて、その画像全体が透明になり、見えなくなります。
# -*- coding:utf-8 -*-
# ラベルクリック時の処理
def click_func(event):
global photo
# 画像全体を透明に設定
photo.blank()
# 1. tkinterをインポート
import tkinter
# 2. メインウインドウを作成
app = tkinter.Tk()
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
file="neko.pgm",
)
# 4. PhotoImageオブジェクトの表示
label = tkinter.Label(
app,
image=photo
)
label.pack()
# ラベルクリック時のイベント受付を設定
label.bind("<ButtonPress>", click_func)
# 5. メインループ
app.mainloop()
copy
copy
は PhotoImage
クラスのオブジェクトのコピーを生成するメソッドです。
# photoはPhotoImageのオブジェクト
new_photo = photo.copy()
get
get
は引数で指定した座標のピクセルデータ(色)を取得するメソッドです。
下記は座標 (100, 100) のピクセルデータを取得する例になります。
# photoはPhotoImageのオブジェクト
photo.get(100, 100)
取得できるデータは下記のような要素が3つのタプルになります。1つ目の要素は赤色の輝度値、2つ目の要素は緑色の輝度値、3つ目の要素は青色の輝度値を示しています。
(173, 201, 80)
put
put
は引数で指定した座標のピクセルデータ(色)を設定するメソッドです。
下記は座標 (100, 100) を赤色(#FF0000
)に設定する例になります。
# photoはPhotoImageのオブジェクト
photo.put("#FF0000", (100, 100))
注意点はピクセルデータの指定方法です。
get
で取得できるのがタプルなので、put
の第1引数にもタプル形式で指定したくなりますが、タプルで指定するとエラーになります。
上記の使用例のように、カラーコードの形式で指定しましょう。
transparency_get
transparency_get
は引数で指定した座標が透明 or 不透明のどちらであるかどうかの情報を取得するメソッドです。
下記は座標 (100, 100) のピクセルが透明かどうかを取得する例になります。
# photoはPhotoImageのオブジェクト
photo.transparency_get(100, 100)
透明な場合は True
が、透明でない場合は False
が取得できます。
transparency_set
transparency_set
は引数で指定した座標の透明 or 不透明を設定するメソッドです。
下記は座標 (100, 100) のピクセルの透明 / 不透明を設定する例になります。
# photoはPhotoImageのオブジェクト
photo.transparency_set(100, 100, True)
ピクセルを透明にしたい場合は True
を、不透明に設定したい場合は False
を第3引数に指定します。
subsample
subsample
は画像を縮小し、新たな PhotoImage
オブジェクトを生成するメソッドです。
# photoはPhotoImageのオブジェクト
new_photo = photo.subsample(2, 1)
subsample
からは新たな PhotoImage
クラスのオブジェクトが返却されます(photo
自体は縮小されない)。
第1引数には横方向、第2引数には縦方向それぞれに対する縮小率を指定します。縮小率が大きいほど、より小さく縮小されます。
第2引数を省略した場合は、第1引数で指定した縮小率で縦横両方向が縮小されます。
引数で指定できるのは整数のみなので注意しましょう。
zoom
zoom
は画像を拡大し、新たな PhotoImage
オブジェクトを生成するメソッドです。
# photoはPhotoImageのオブジェクト
new_photo = photo.zoom(2, 1)
zoom
からは新たな PhotoImage
クラスのオブジェクトが返却されます(photo
自体は拡大されない)。
第1引数には横方向、第2引数には縦方向それぞれに対する拡大率を指定します。拡大率が大きいほど、より大きく拡大されます。
第2引数を省略した場合は、第1引数で指定した拡大率で縦横両方向が拡大されます。
引数で指定できるのは整数のみなので注意しましょう。
write
write
は PhotoImage
クラスのオブジェクトの画像をファイルとして保存するメソッドです。
# photoはPhotoImageのオブジェクト
photo.write("output.png)
どのフォーマットの画像として保存するかは引数で指定するファイル名の拡張子で指定することも可能ですし、第2引数で指定することもできます。
さらに第3引数で画像のどの座標位置からg
# photoはPhotoImageのオブジェクト
photo.write(
"cute_cat.pgm",
"ppm",
(100, 100)
)
例えば上記のように引数を指定すれば、画像の座標 (100, 100) からのみを画像ファイルとして保存することが可能です。
BitmapImage
クラスで画像を扱う
次は BitmapImage
クラスでの画像の扱い方について解説していきます。
BitmapImage
クラスでの基本的な画像の扱い方
BitmapImage
においても基本的な画像の扱い方は PhotoImage
クラスと同じです。
ただし BitmapImage
クラスで扱える画像のフォーマットは下記の一つのみです。
- XBM
XBM がどんな画像フォーマットであるかは下記の Wikipedia のページなどを読むと理解できると思います。
https://ja.wikipedia.org/wiki/XBM
XBM のポイントは下記の二つだと思います。
- テキスト形式で作成できる
- 扱えるのは2値画像
画像の各バイトをC言語の配列の要素として記述するだけで XBM ファイルを作成することができます。バイナリ形式ではなくテキスト形式で記述することが可能です。
ただし扱えるのは2値画像だけなので、使い道は少ないと思います。1ピクセルあたりのデータサイズが1ビットなのでサイズ的に軽いのは良いのですが…。
扱える画像フォーマットは異なりますが、基本的な画像の扱い方は PhotoImage
クラスと同じです。
下のスクリプトは、BitmapImage
クラスでアプリ上に画像を表示する簡単な例になります。
# -*- coding:utf-8 -*-
# 1. tkinterをインポート
import tkinter
# 2. メインウインドウを作成
app = tkinter.Tk()
# 3. BitmapImageオブジェクトの作成
bitmap = tkinter.BitmapImage(
file="image.xbm",
)
# 4. BitmapImageオブジェクトの表示
label = tkinter.Label(
app,
image=bitmap
)
label.pack()
# 5. メインループ
app.mainloop()
ここからは BitmapImage
コンストラクタへのキーワード指定による設定について解説していきます。メソッドに関しては、PhotoImage
のメソッドの一部が使用可能です。なので、どのメソッドが使用可能であるかのみについて解説したいと思います。
スポンサーリンク
BitmapImage
クラスの設定
PhotoImage
同様にコンストラクタにキーワード指定形式で生成するオブジェクトの設定行うことが可能です。
file
file
キーワードでファイル名を指定することで、読み込む画像ファイルを設定することができます。
# 3. BitmapImageオブジェクトの作成
bitmap = tkinter.BitmapImage(
file="image.xbm"
)
data
また、data
キーワードでデータのリストを指定すれば、ファイルからではなく画像データを読み込んで画像オブジェクトを生成することができます。
data
で指定する画像データも下記の画像フォーマットである必要があります。
- XBM
data
で画像データを読み込んで表示するサンプルスクリプトは下記のようになります。
要はファイルから読み込んだデータをdata
に指定すれば良いです。
# -*- coding:utf-8 -*-
# 1. tkinterをインポート
import tkinter
# 2. メインウインドウを作成
app = tkinter.Tk()
# 3. BitmapImageオブジェクトの作成
f = open("image.xbm")
data = f.read()
f.close()
bitmap = tkinter.BitmapImage(
data=data
)
# 4. BitmapImageオブジェクトの表示
label = tkinter.Label(
app,
image=bitmap
)
label.pack()
# 5. メインループ
app.mainloop()
foreground
・background
まず前提として、XBM 形式の画像は各ピクセルのデータが “1” or “0” の2値のみになります。
foreground
ではピクセルのデータが “1” の色を、background
ではピクセルのデータが “0” の色を設定することができます。
例えば下記のように設定すれば、データが “1” のピクセルを赤色に、データが “0” のピクセルを青色にすることができます。
# 3. BitmapImageオブジェクトの作成
bitmap = tkinter.BitmapImage(
file="image.xbm",
foreground="red",
background="blue"
)
指定しなかった場合は下記のように foreground
と background
が設定されますので、白黒画像として表示されることになります。
foreground
:黒background
:白
maskfile
・maskdata
maskfile
に file
or data
で指定した画像と同じサイズのマスクデータのファイル指定することで、表示する画像をマスクすることができます。マスクとは、具体的に画像の一部を透明にする処理です。
マスクデータも XBM 同様に2値データであり、”0″ のピクセルは透明に表示されるようになります(つまり表示されない)。
maskfile
と maskdata
では、file
と data
の違い同様、ファイルを指定するかデータを指定するかが異なります。
ただし、私の環境では上手く動作しませんでした…。
BitmapImage
クラスのメソッド
BitmapImage
クラスのオブジェクトで実行できるメソッドは下記の4つになります。
configure
type
width
height
使い方や動作は PhotoImage
クラスのものと同様になります。
Tkinter でもっと多くの画像フォーマットを扱う方法
ここまで解説してきたように、Tkinter の PhotoImage
クラス & BitmapImage
クラスで扱える画像フォーマットは下記の5つになります。
- PGM
- PPM
- GIF
- PNG
- XBM
JPEG などのもっと多種の画像フォーマットを扱いたい、もっと高度な画像処理を簡単に行いたいという場合は、PIL(Pillow) や OpenCV を併用するのがオススメです。
下記の手順を踏めば、より多種の画像フォーマットを読み込んだり、高度な画像処理を行ったりした結果を GUI アプリに簡単に表示することが可能です。
- PIL や OpenCV で画像を読み込む
- PIL や OpenCV で画像処理を行う
- 画像処理後の画像を Tkinter で扱える画像オブジェクトに変換する
- 変換後の画像を Tkinter で GUI アプリに表示する
3. で行う変換については下記で解説していますので、是非画像処理アプリ等を開発してみたい方はこちらも合わせて読んでみてください。
【Python】PIL ⇔ OpenCV2 ⇔ Tkinter 画像オブジェクトの相互変換スポンサーリンク
まとめ
このページでは Tkinter で PhotoImage
クラスと BitmaipImage
クラスを用いて画像を扱う方法について解説しました。
画像を扱うことで、画像を表示してアプリの見た目を華やかにしたり、画像処理アプリを作成して画像処理後の画像を表示したりすることが可能になります。
画像処理自体は Tkinter は得意ではないので PIL や OpenCV 等のライブラリを利用する方が良いと思います。
しかし GUI アプリ上で画像処理の設定を行って GUI アプリ上で画像処理の結果を表示したい場合はしっかりと Tkinter での画像の扱い方は理解しておく必要があります。
ですので、subsample
や zoom
メソッド、gamma
や palette
設定での画像処理についてはそこまで深く理解する必要はないと思いますが、特に PhotoImage
オブジェクトを作成したり、そのオブジェクトをアプリ上に表示するための方法についてはしっかり理解しておくと良いと思います!
オススメ参考書(PR)
Tkinter に興味がある方には下記のPythonでつくる ゲーム開発 入門講座がオススメです。
Tkinter をゲーム開発を通して「楽しく学ぶ」ことができます。Python 入門者、Tkinter 入門者の方にオススメです。
作成するゲームの中でも画像を扱いますので、Tkinter での画像の扱い方に興味のある方にもオススメの本になります!