Tkinter の使い方:PhotoImage・BitmapImageクラスで画像を扱う

Tkinterで画像を扱う方法の解説ページアイキャッチ

このページでは、Tkinter で画像を扱う方法について解説していきたいと思います。

画像の使いどころ

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 クラスでアプリ上に画像を表示する簡単な例になります。

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 クラスで画像を扱う基本的な流れは次のようになります。

  1. tkinter をインポート
  2. メインウィンドウを作成
  3. PhotoImage オブジェクトの作成
  4. PhotoImage オブジェクトの表示
  5. メインループ

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 キーワードでファイル名を指定することで、読み込む画像ファイルを設定することができます。

fileの設定例
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
	file="neko.pgm"
)

data

また、data キーワードでデータのリストを指定すれば、ファイルからではなく画像データを読み込んで画像オブジェクトを生成することができます。

data で指定する画像データも下記の画像フォーマットである必要があります。

  • PGM
  • PPM
  • GIF
  • PNG

data で画像データを読み込んで表示するサンプルスクリプトは下記のようになります。

要はファイルから読み込んだデータを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()

widthheight

widthheight の指定により画像を読み込むサイズを指定できます。

ただし、どの位置から読み込むからは指定することはできず、画像の左上から widthheight で指定したサイズ分が読み込まれることになります。

例えば下記のサンプルスクリプトでは画像全体が表示されますが、

widthとheightを設定しない例
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
	file="neko.pgm"
)

下記のように widthheight を指定することで画像の左上から 200 x 200 px 分のみが表示されるようになります。

widthとheightの設定例
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
	file="neko.pgm",
	width=200,
	height=200
)

widthheight が画像サイズを超える場合でも指定した widthheight 分の画像として扱われます。ただし画像サイズ超えた部分は透明のピクセルとして表示されます(つまり背景がそのまま表示される)。

format

format ではどのフォーマットの画像を読み込むかを設定することができます。

指定できる format は下記の3つになります。

  • "ppm"
  • "gif"
  • "png"

"pgm" は指定できませんので、PGM ファイルの時は "ppm" を指定します。

formatの設定例
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
	file="neko.pgm"
	format="ppm"
)

ただし基本的に読み込むファイルの拡張子や画像データのヘッダーから自動的に画像のフォーマットは設定されるようですので、無理に format指定する必要はないと思います。

gamma

gamma を浮動小数点の値を指定することで画像に対してガンマ補正を行うことができるようです。

ただし私の環境では動作してくれませんでした…。

gammaの設定例?
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
	file="neko.pgm"
	gamma=0.5
)

palette

palette を指定することで画像の簡単な色変換行うことができるようです。

ただし私の環境では動作してくれませんでした…。

下記のように palette に1つの数字を指定すれば、グレースケール画像に色変換され、

paletteの設定例1?
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
	file="neko.png",
	palette="256"
)

下記のように palette に “/” (スラッシュ)で区切って赤・緑・青の3つ色数を指定すれば、元々の画像の色数(例えば赤・緑・青それぞれ256色)を指定した色数で表現するように色変換されるようです。

paletteの設定例2?
# 3. PhotoImageオブジェクトの作成
photo = tkinter.PhotoImage(
	file="neko.png",
	palette="7/7/4"
)
MEMO

実際に動作させられなかった部分は仕様書やソースコードを読んだ結果を解説として記述しています

もし動作させ方が分かった場合は追記します

スポンサーリンク

PhotoImage クラスのメソッド

次は PhotoImage クラスのオブジェクトで実行できるメソッドについて解説していきます。

特に subsamplezoom に関しては下記ページで、

アプリ上に画像を表示する方法の解説ページアイキャッチ【Python】Tkinter のみで GUI アプリに画像を表示する

putgettransparency_settransparency_get では下記ページで実際の利用例を紹介していますので、こちらも合わせてお読みいただければと思います。

【Python】Tkinter PhotoImage の get・put を利用してピクセル単位で画像処理を行う(透過処理も)

widthheight

width と height は実行したオブジェクトの画像の幅・高さを取得するメソッドです。

widthとheightの使用例
# photoはPhotoImageのオブジェクト
width = photo.width()
height = photo.height()

コンストラクタで width や height を指定した場合は、width()height() 実行時にはその指定した値が返却されます。

type

type はそのオブジェクトの画像タイプを取得するメソッドです。

取得できる具体的なタイプは下記の二つになります。

  • "photo"
  • "bitmap"
typeの使用例
# photoはPhotoImageのオブジェクト
photo.type()

PhotoImage クラスのオブジェクトであれば、必ず "photo" が返却されるはずです。

configure

configure はコンストラクタ実行時に指定した画像オブジェクトの設定を変更するメソッドです。

指定できるキーワードは PhotoImage クラスの設定で紹介したものになります。

下記が configure メソッドの使用例です。

画像を表示するラベルをクリックされた際に click_func 関数が実行され、その中で configure() メソッド実行されます。

さらに configure で file を指定していますので、ラベルクリックすると表示する画像が変化することになります("neko.pgm" から "cute_cat.png" に変化)。

configureの使用例
# -*- 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 メソッドが実行されて、その画像全体が透明になり、見えなくなります。

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

copyPhotoImage クラスのオブジェクトのコピーを生成するメソッドです。

copyの使用例
# photoはPhotoImageのオブジェクト
new_photo = photo.copy()

get

get は引数で指定した座標のピクセルデータ(色)を取得するメソッドです。

下記は座標 (100, 100) のピクセルデータを取得する例になります。

getの使用例
# photoはPhotoImageのオブジェクト
photo.get(100, 100)

取得できるデータは下記のような要素が3つのタプルになります。1つ目の要素は赤色の輝度値、2つ目の要素は緑色の輝度値、3つ目の要素は青色の輝度値を示しています。

(173, 201, 80)

put

put は引数で指定した座標のピクセルデータ(色)を設定するメソッドです。

下記は座標 (100, 100) を赤色(#FF0000)に設定する例になります。

putの使用例
# photoはPhotoImageのオブジェクト
photo.put("#FF0000", (100, 100))

注意点はピクセルデータの指定方法です。

get で取得できるのがタプルなので、put の第1引数にもタプル形式で指定したくなりますが、タプルで指定するとエラーになります。

上記の使用例のように、カラーコードの形式で指定しましょう。

transparency_get

transparency_get は引数で指定した座標が透明 or 不透明のどちらであるかどうかの情報を取得するメソッドです。

下記は座標 (100, 100) のピクセルが透明かどうかを取得する例になります。

transparency_getの使用例
# photoはPhotoImageのオブジェクト
photo.transparency_get(100, 100)

透明な場合は True が、透明でない場合は False が取得できます。

transparency_set

transparency_set は引数で指定した座標の透明 or 不透明を設定するメソッドです。

下記は座標 (100, 100) のピクセルの透明 / 不透明を設定する例になります。

transparency_setの使用例
# photoはPhotoImageのオブジェクト
photo.transparency_set(100, 100, True)

ピクセルを透明にしたい場合は True を、不透明に設定したい場合は False を第3引数に指定します。

subsample

subsample は画像を縮小し、新たな PhotoImage オブジェクトを生成するメソッドです。

subsampleの使用例
# photoはPhotoImageのオブジェクト
new_photo = photo.subsample(2, 1)

subsample からは新たな PhotoImage クラスのオブジェクトが返却されます(photo 自体は縮小されない)。

第1引数には横方向、第2引数には縦方向それぞれに対する縮小率を指定します。縮小率が大きいほど、より小さく縮小されます。

第2引数を省略した場合は、第1引数で指定した縮小率で縦横両方向が縮小されます。

引数で指定できるのは整数のみなので注意しましょう。

zoom

zoom は画像を拡大し、新たな PhotoImage オブジェクトを生成するメソッドです。

zoomの使用例
# photoはPhotoImageのオブジェクト
new_photo = photo.zoom(2, 1)

zoom からは新たな PhotoImage クラスのオブジェクトが返却されます(photo 自体は拡大されない)。

第1引数には横方向、第2引数には縦方向それぞれに対する拡大率を指定します。拡大率が大きいほど、より大きく拡大されます。

第2引数を省略した場合は、第1引数で指定した拡大率で縦横両方向が拡大されます。

引数で指定できるのは整数のみなので注意しましょう。

write

writePhotoImage クラスのオブジェクトの画像をファイルとして保存するメソッドです。

writeの使用例1
# photoはPhotoImageのオブジェクト
photo.write("output.png)

どのフォーマットの画像として保存するかは引数で指定するファイル名の拡張子で指定することも可能ですし、第2引数で指定することもできます。

さらに第3引数で画像のどの座標位置からg

writeの使用例2
# 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 クラスでアプリ上に画像を表示する簡単な例になります。

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 キーワードでファイル名を指定することで、読み込む画像ファイルを設定することができます。

fileの設定例
# 3. BitmapImageオブジェクトの作成
bitmap = tkinter.BitmapImage(
	file="image.xbm"
)

data

また、data キーワードでデータのリストを指定すれば、ファイルからではなく画像データを読み込んで画像オブジェクトを生成することができます。

data で指定する画像データも下記の画像フォーマットである必要があります。

  • XBM

data で画像データを読み込んで表示するサンプルスクリプトは下記のようになります。

要はファイルから読み込んだデータを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()

foregroundbackground

まず前提として、XBM 形式の画像は各ピクセルのデータが “1” or “0” の2値のみになります。

foregroundではピクセルのデータが “1” の色を、background ではピクセルのデータが “0” の色を設定することができます。

例えば下記のように設定すれば、データが “1” のピクセルを赤色に、データが “0” のピクセルを青色にすることができます。

dataの設定例
# 3. BitmapImageオブジェクトの作成
bitmap = tkinter.BitmapImage(
	file="image.xbm",
	foreground="red",
	background="blue"
)

指定しなかった場合は下記のように foreground と background が設定されますので、白黒画像として表示されることになります。

  1. foreground:黒
  2. background:白

maskfilemaskdata

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 アプリに簡単に表示することが可能です。

  1. PIL や OpenCV で画像を読み込む
  2. PIL や OpenCV で画像処理を行う
  3. 画像処理後の画像を Tkinter で扱える画像オブジェクトに変換する
  4. 変換後の画像を Tkinter で GUI アプリに表示する

3. で行う変換については下記で解説していますので、是非画像処理アプリ等を開発してみたい方はこちらも合わせて読んでみてください。

画像オブジェクト変換方法の解説ページアイキャッチ【Python】PIL ⇔ OpenCV2 ⇔ Tkinter 画像オブジェクトの相互変換

スポンサーリンク

まとめ

このページでは Tkinter で PhotoImage クラスと BitmaipImage クラスを用いて画像を扱う方法について解説しました。

画像を扱うことで、画像を表示してアプリの見た目を華やかにしたり、画像処理アプリを作成して画像処理後の画像を表示したりすることが可能になります。

画像処理自体は Tkinter は得意ではないので PIL や OpenCV 等のライブラリを利用する方が良いと思います。

しかし GUI アプリ上で画像処理の設定を行って GUI アプリ上で画像処理の結果を表示したい場合はしっかりと Tkinter での画像の扱い方は理解しておく必要があります。

ですので、subsamplezoom メソッド、gammapalette 設定での画像処理についてはそこまで深く理解する必要はないと思いますが、特に PhotoImage オブジェクトを作成したり、そのオブジェクトをアプリ上に表示するための方法についてはしっかり理解しておくと良いと思います!

オススメ参考書

Tkinter に興味がある方には下記のPythonでつくる ゲーム開発 入門講座がオススメです。

Tkinter をゲーム開発を通して「楽しく学ぶ」ことができます。Python 入門者、Tkinter 入門者の方にオススメです。

作成するゲームの中でも画像を扱いますので、Tkinter での画像の扱い方に興味のある方にもオススメの本になります!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です