[Python Tkinter] 表示中の画像を保存する方法【Canvasウィジェット】
PythonのTkinterでCanvasウィジェットに表示中の画像を保存するには、Pillowライブラリ(PIL)を使用します。
まず、Canvasに表示する画像をPillowのImage
オブジェクトとして読み込み、Canvasに描画します。
保存する際には、元のImage
オブジェクトをsave()メソッド
でファイルに保存します。
Canvas自体の内容を保存する場合は、Canvasの内容をPillowのImageGrab
モジュールでキャプチャし、保存することも可能です。
Canvasに画像を表示する手順
Pillowで画像を読み込む
PythonのPillowライブラリを使用して、画像ファイルを読み込むことができます。
以下のサンプルコードでは、Image
モジュールを使って画像を開きます。
from PIL import Image
# 画像ファイルを読み込む
image = Image.open("sample_image.jpg")
このコードを実行すると、指定した画像ファイルが読み込まれ、image変数
に格納されます。
Canvasに画像を描画する
TkinterのCanvasウィジェットを使用して、読み込んだ画像を表示することができます。
以下のサンプルコードでは、Canvasに画像を描画する方法を示します。
import tkinter as tk
from PIL import Image, ImageTk
# Tkinterのウィンドウを作成
root = tk.Tk()
# 画像を読み込む
image = Image.open("sample_image.jpg")
photo = ImageTk.PhotoImage(image)
# Canvasを作成
canvas = tk.Canvas(root, width=image.width, height=image.height)
canvas.pack()
# Canvasに画像を描画
canvas.create_image(0, 0, anchor=tk.NW, image=photo)
# ウィンドウを表示
root.mainloop()

このコードを実行すると、指定した画像がTkinterのウィンドウに表示されます。
Canvas上で画像を操作する方法
Canvas上で画像を操作するためには、画像の位置を変更したり、サイズを変更したりすることができます。
以下のサンプルコードでは、画像を移動させる方法を示します。
import tkinter as tk
from PIL import Image, ImageTk
# Tkinterのウィンドウを作成
root = tk.Tk()
# 画像を読み込む
image = Image.open("sample_image.jpg")
photo = ImageTk.PhotoImage(image)
# Canvasを作成
canvas = tk.Canvas(root, width=image.width, height=image.height)
canvas.pack()
# Canvasに画像を描画
image_id = canvas.create_image(0, 0, anchor=tk.NW, image=photo)
# 画像を移動する関数
def move_image():
canvas.move(image_id, 10, 10) # 画像を右下に10ピクセル移動
# ボタンを作成して画像を移動
button = tk.Button(root, text="画像を移動", command=move_image)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、ボタンをクリックすることで画像が右下に移動します。

これにより、Canvas上での画像操作が可能になります。
表示中の画像を保存する方法
Pillowのsave()メソッドを使った画像保存
Pillowライブラリのsave()メソッド
を使用すると、読み込んだ画像を指定したファイル名で保存することができます。
以下のサンプルコードでは、画像を保存する方法を示します。
from PIL import Image
# 画像ファイルを読み込む
image = Image.open("sample_image.jpg")
# 画像を保存する
image.save("saved_image.png")
このコードを実行すると、sample_image.jpg
がsaved_image.png
として保存されます。
ファイル形式は拡張子によって自動的に決定されます。
Canvasの内容をキャプチャして保存する方法
Canvasに描画された内容を画像として保存するには、ImageGrab
モジュールを使用します。
以下のサンプルコードでは、Canvasの内容をキャプチャして保存する方法を示します。
ImageGrabモジュールの使い方
ImageGrab
モジュールを使用することで、画面の特定の領域をキャプチャすることができます。
以下のコードでは、Canvasの内容をキャプチャする方法を示します。
import tkinter as tk
from PIL import Image, ImageTk, ImageGrab
# Tkinterのウィンドウを作成
root = tk.Tk()
# Canvasを作成
canvas = tk.Canvas(root, width=300, height=300)
canvas.pack()
# Canvasに矩形を描画
canvas.create_rectangle(50, 50, 250, 250, fill="blue")
# Canvasの内容をキャプチャして保存する関数
def save_canvas():
# Canvasの座標を取得
x = root.winfo_x() + canvas.winfo_x()
y = root.winfo_y() + canvas.winfo_y()
width = canvas.winfo_width()
height = canvas.winfo_height()
# 画像をキャプチャ
image = ImageGrab.grab(bbox=(x, y, x + width, y + height))
image.save("canvas_image.png")
# ボタンを作成してCanvasを保存
button = tk.Button(root, text="Canvasを保存", command=save_canvas)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、ボタンをクリックすることでCanvasの内容がcanvas_image.png
として保存されます。
Canvas全体をキャプチャする方法
Canvas全体をキャプチャするには、ImageGrab.grab()メソッド
を使用し、Canvasのウィンドウ全体の座標を指定します。
上記のコード例で示したように、bbox
引数にCanvasの位置とサイズを指定することで、全体をキャプチャできます。
特定の領域をキャプチャする方法
特定の領域をキャプチャする場合も、ImageGrab.grab()メソッド
を使用します。
bbox
引数にキャプチャしたい領域の座標を指定することで、その部分だけを画像として保存できます。
以下のサンプルコードでは、特定の領域をキャプチャする方法を示します。
import tkinter as tk
from PIL import Image, ImageGrab
# Tkinterのウィンドウを作成
root = tk.Tk()
# Canvasを作成
canvas = tk.Canvas(root, width=300, height=300)
canvas.pack()
# Canvasに矩形を描画
canvas.create_rectangle(50, 50, 250, 250, fill="blue")
# 特定の領域をキャプチャして保存する関数
def save_partial_canvas():
# キャプチャしたい領域の座標を指定
bbox = (50, 50, 250, 250) # (左上x, 左上y, 右下x, 右下y)
# 画像をキャプチャ
image = ImageGrab.grab(bbox=bbox)
image.save("partial_canvas_image.png")
# ボタンを作成して特定の領域を保存
button = tk.Button(root, text="特定の領域を保存", command=save_partial_canvas)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、ボタンをクリックすることで指定した領域がpartial_canvas_image.png
として保存されます。
画像保存時の注意点
ファイル形式の選択(PNG, JPEGなど)
画像を保存する際には、ファイル形式を選択することが重要です。
一般的な画像形式には以下のようなものがあります。
ファイル形式 | 特徴 |
---|---|
PNG | 可逆圧縮、透明度をサポート、画質が劣化しない |
JPEG | 非可逆圧縮、ファイルサイズが小さくなるが画質が劣化する |
BMP | 圧縮なし、画質が高いがファイルサイズが大きい |
GIF | アニメーションをサポート、256色まで |
選択する形式は、用途に応じて決定します。
例えば、透明な背景が必要な場合はPNG、ファイルサイズを小さくしたい場合はJPEGが適しています。
画像の解像度と品質
画像の解像度は、画像の詳細度を示す指標であり、通常はDPI(ドット・パー・インチ)で表されます。
解像度が高いほど、画像は鮮明になりますが、ファイルサイズも大きくなります。
以下のポイントに注意してください。
- 高解像度: 印刷物や詳細な表示が必要な場合に適しています。
- 低解像度: ウェブ用や小さな表示に適しており、ファイルサイズを小さく保つことができます。
また、JPEG形式で保存する際には、品質を指定することができます。
品質が高いほど画質は良くなりますが、ファイルサイズも大きくなります。
保存先の指定方法
画像を保存する際には、保存先のパスを指定する必要があります。
以下のサンプルコードでは、指定したパスに画像を保存する方法を示します。
from PIL import Image
# 画像ファイルを読み込む
image = Image.open("sample_image.jpg")
# 画像を指定したパスに保存する
image.save("/path/to/save/saved_image.png")
このコードでは、/path/to/save/
の部分を実際の保存先のパスに置き換える必要があります。
保存先のディレクトリが存在しない場合、エラーが発生するため、事前にディレクトリを作成しておくことが重要です。
応用例
Canvas上で編集した画像を保存する
Canvas上で画像を編集した後、その結果を保存することができます。
以下のサンプルコードでは、画像をCanvasに表示し、矩形を描画した後にその内容を保存します。
import tkinter as tk
from PIL import Image, ImageTk, ImageGrab
# Tkinterのウィンドウを作成
root = tk.Tk()
# 画像を読み込む
image = Image.open("sample_image.jpg")
photo = ImageTk.PhotoImage(image)
# Canvasを作成
canvas = tk.Canvas(root, width=image.width, height=image.height)
canvas.pack()
# Canvasに画像を描画
canvas.create_image(0, 0, anchor=tk.NW, image=photo)
# 矩形を描画する
canvas.create_rectangle(50, 50, 250, 250, outline="red", width=5)
# Canvasの内容を保存する関数
def save_canvas():
x = root.winfo_x() + canvas.winfo_x()
y = root.winfo_y() + canvas.winfo_y()
width = canvas.winfo_width()
height = canvas.winfo_height()
image = ImageGrab.grab(bbox=(x, y, x + width, y + height))
image.save("edited_canvas_image.png")
# ボタンを作成してCanvasを保存
button = tk.Button(root, text="編集した画像を保存", command=save_canvas)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、画像に矩形を描画した後、ボタンをクリックすることで編集した内容がsaved_canvas_image.png
として保存されます。
複数の画像をCanvasに表示して保存する
複数の画像をCanvasに表示し、それらをまとめて保存することも可能です。
以下のサンプルコードでは、2つの画像をCanvasに表示し、保存します。
import tkinter as tk
from PIL import Image, ImageTk, ImageGrab
# Tkinterのウィンドウを作成
root = tk.Tk()
# 画像を読み込む
image1 = Image.open("sample_image1.jpg")
image2 = Image.open("sample_image2.jpg")
photo1 = ImageTk.PhotoImage(image1)
photo2 = ImageTk.PhotoImage(image2)
# Canvasを作成
canvas = tk.Canvas(root, width=image1.width, height=image1.height)
canvas.pack()
# Canvasに画像を描画
canvas.create_image(0, 0, anchor=tk.NW, image=photo1)
canvas.create_image(100, 100, anchor=tk.NW, image=photo2)
# Canvasの内容を保存する関数
def save_canvas():
x = root.winfo_x() + canvas.winfo_x()
y = root.winfo_y() + canvas.winfo_y()
width = canvas.winfo_width()
height = canvas.winfo_height()
image = ImageGrab.grab(bbox=(x, y, x + width, y + height))
image.save("multiple_images_canvas.png")
# ボタンを作成してCanvasを保存
button = tk.Button(root, text="複数の画像を保存", command=save_canvas)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、2つの画像がCanvasに表示され、ボタンをクリックすることでその内容がmultiple_images_canvas.png
として保存されます。
Canvasに描画した図形やテキストを含めて保存する
Canvasに描画した図形やテキストを含めて保存することもできます。
以下のサンプルコードでは、テキストと図形を描画し、その内容を保存します。
import tkinter as tk
from PIL import Image, ImageTk, ImageGrab
# Tkinterのウィンドウを作成
root = tk.Tk()
# Canvasを作成
canvas = tk.Canvas(root, width=300, height=300)
canvas.pack()
# 図形を描画
canvas.create_rectangle(50, 50, 250, 250, fill="green")
canvas.create_oval(100, 100, 200, 200, fill="yellow")
# テキストを描画
canvas.create_text(150, 150, text="Hello, Canvas!", font=("Arial", 20))
# Canvasの内容を保存する関数
def save_canvas():
x = root.winfo_x() + canvas.winfo_x()
y = root.winfo_y() + canvas.winfo_y()
width = canvas.winfo_width()
height = canvas.winfo_height()
image = ImageGrab.grab(bbox=(x, y, x + width, y + height))
image.save("shapes_and_text_canvas.png")
# ボタンを作成してCanvasを保存
button = tk.Button(root, text="図形とテキストを保存", command=save_canvas)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、図形とテキストが描画されたCanvasが表示され、ボタンをクリックすることでその内容がshapes_and_text_canvas.png
として保存されます。
画像の一部を切り取って保存する
Canvas上の画像の一部を切り取って保存することも可能です。
以下のサンプルコードでは、Canvasに表示された画像の特定の領域を切り取って保存します。
import tkinter as tk
from PIL import Image, ImageTk, ImageGrab
# Tkinterのウィンドウを作成
root = tk.Tk()
# 画像を読み込む
image = Image.open("sample_image.jpg")
photo = ImageTk.PhotoImage(image)
# Canvasを作成
canvas = tk.Canvas(root, width=image.width, height=image.height)
canvas.pack()
# Canvasに画像を描画
canvas.create_image(0, 0, anchor=tk.NW, image=photo)
# 特定の領域を切り取って保存する関数
def save_cropped_image():
# 切り取りたい領域の座標を指定
bbox = (50, 50, 250, 250) # (左上x, 左上y, 右下x, 右下y)
# 画像をキャプチャ
cropped_image = ImageGrab.grab(bbox=bbox)
cropped_image.save("cropped_image.png")
# ボタンを作成して特定の領域を保存
button = tk.Button(root, text="画像の一部を保存", command=save_cropped_image)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、指定した領域がcropped_image.png
として保存されます。
保存時にファイル名を動的に変更する方法
保存時にファイル名を動的に変更することで、同じ名前のファイルが上書きされるのを防ぐことができます。
以下のサンプルコードでは、現在の日時をファイル名に追加して保存します。
import tkinter as tk
from PIL import Image, ImageTk, ImageGrab
from datetime import datetime
# Tkinterのウィンドウを作成
root = tk.Tk()
# 画像を読み込む
image = Image.open("sample_image.jpg")
photo = ImageTk.PhotoImage(image)
# Canvasを作成
canvas = tk.Canvas(root, width=image.width, height=image.height)
canvas.pack()
# Canvasに画像を描画
canvas.create_image(0, 0, anchor=tk.NW, image=photo)
# Canvasの内容を保存する関数
def save_canvas():
x = root.winfo_x() + canvas.winfo_x()
y = root.winfo_y() + canvas.winfo_y()
width = canvas.winfo_width()
height = canvas.winfo_height()
image = ImageGrab.grab(bbox=(x, y, x + width, y + height))
# 現在の日時を取得してファイル名に追加
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"canvas_image_{timestamp}.png"
image.save(filename)
# ボタンを作成してCanvasを保存
button = tk.Button(root, text="動的にファイル名を変更して保存", command=save_canvas)
button.pack()
# ウィンドウを表示
root.mainloop()
このコードを実行すると、Canvasの内容が現在の日時を含むファイル名で保存されます。
これにより、同じ名前のファイルが上書きされることを防げます。
まとめ
この記事では、PythonのTkinterを使用してCanvasに画像を表示し、その画像を保存する方法について詳しく解説しました。
具体的には、Pillowライブラリを利用して画像を読み込み、Canvasに描画し、さらに編集した内容を保存する手順を紹介しました。
また、複数の画像を表示したり、図形やテキストを含めて保存する方法、特定の領域を切り取って保存する技術についても触れました。
これらの知識を活用して、実際のプロジェクトで画像処理を行う際に、ぜひ試してみてください。