MikkelBybjerg
MikkelBybjerg

Reputation: 59

Why does Tkinter Canvas widget show images at a wrong scale?

I'm trying to open image files and display them in python 3.8 using Tkinter and Pillow, but something is scaling the images wrong on my screen.

import tkinter as tk
from PIL import Image, ImageTk


class ViewingWindow(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.image = None
        self.canvas = tk.Canvas(self, width=500, height=500)
        self.canvas.pack()

    def setImage(self, img):
        self.image = img
        print(img.width())
        print(img.height())
        print(self.canvas["width"])
        print(self.canvas["height"])
        self.canvas.create_image(0, 0, anchor=tk.NW, image=img)


window = tk.Tk()

canvas = ViewingWindow(window)
canvas.pack()

img = Image.open("500x500.jpg")
img = ImageTk.PhotoImage(img)
canvas.setImage(img)

window.mainloop()

This is the result, shown for reference is Windows image viewer at "show actual size", and Gimp at scaling=100%: enter image description here

The 4 print statements all show "500", every part of the system seems to agree that the image is shown at 500x500, except the actual pixels on the screen. For whatever reason it's scaled to something close to 750x750, what in the world is scaling my image? This is consistent for all images I've tried to open in Tkinter, and regardless on window size and widget sizes.

Tested on Windows 10 with screen resolution 1920x1080.

Upvotes: 1

Views: 994

Answers (1)

jizhihaoSAMA
jizhihaoSAMA

Reputation: 12672

it's scaled to something close to 750x750

750/500 = 150%.It seems that your system zoom ratio is 150%.

enter image description here To show the right image size.Just like furas said,you need to use DPI awareness.Read the problem in MSDN official doc

About DPI awareness.

To solve the problem,you can set the DPI awareness in your code.(Or you can change the zoom ratio to 100%) In my PC,the are not the same size without DPI awareness.Now after set the DPI awareness: enter image description here

Add this in your code:

import ctypes

ctypes.windll.shcore.SetProcessDpiAwareness(2) # this could only be used when your version of windows >= 8.1

Upvotes: 2

Related Questions