tkinterで画像ビューア(Canvas.create_image周りの補足)


209行目のoffsetや253行目のcreate_image周りを整理する。

・基本

canvas_width = 400
canvas_height = 400
self.canvas = tkinter.Canvas(self.master, bg='red', width=canvas_width, height=canvas_height)
self.canvas.pack()
self.img = Image.open('sora.png')
self.tk_img = ImageTk.PhotoImage(self.img)
self.canvas.create_image(
canvas_width // 2, canvas_height // 2, image=self.tk_img, anchor='c'
)

create_imageは、canvasの(canvas_width//2, canvas_height//2)の位置に画像の中心を持ってくるという命令。anchorの対象が"canvas"ではなく"画像"であることに注意。anchorのデフォルトは"c"。

・アフィン変換

mat = np.eye(3)
mat[0, 2] = float((canvas_width - self.img.width) / 2)
mat[1, 2] = float((canvas_height - self.img.width) / 2)

inv_mat = np.linalg.inv(mat)
pil_transformed_image = self.img.transform(
(canvas_width, canvas_height),
Image.AFFINE,
tuple(inv_mat.flatten()),
Image.NEAREST,
)

self.tk_img = ImageTk.PhotoImage(pil_transformed_image)
self.canvas.create_image(
canvas_width // 2, canvas_height // 2, image=self.tk_img, anchor='c'
)

matは、画像中心をキャンパス中心に持っていく行列。
transformで(canvas_width, canvas_height)の画像を生成。
create_imageは「基本」と同じでOK。上記サイトのように(0, 0, anchor='nw')にする必要はない。なお、逆に「基本」で(0, 0, anchor='nw')を使うと表示がおかしくなるので注意。画像中心をキャンパス中心に持っていった場合のみ使える。