0

The code provided here is:

import tkinter as tk
from PIL import Image, ImageTk
from pathlib import Path


class App(tk.Tk):
    def __init__(self):
        super().__init__()
    self.geometry('600x600')
    
    self.img_path = Path(r'D:\Python\Lena.jpg')
    self.img = Image.open(self.img_path)
    self.img_rgb = self.img.convert('RGB')
    dim_x, dim_y = self.img_rgb.size
    self.img_tk = ImageTk.PhotoImage(self.img_rgb.resize((dim_x, dim_y)))
    
    self.canvas = tk.Canvas(self)
    self.canvas.create_image(dim_x // 2, dim_y // 2, image=self.img_tk)
    self.canvas.pack(expand=True, fill=tk.BOTH)

    self.rgb_var = tk.StringVar(self, '0 0 0')
    self.rgb_label = tk.Label(self, textvariable=self.rgb_var)
    self.rgb_label.pack()

    self.bind('<Motion>', lambda e: self.get_rgb(e))

def get_rgb(self, event):
    x, y = event.x, event.y
    try:
        rgb = self.img_rgb.getpixel((x, y))
        self.rgb_var.set(rgb)
    except IndexError:
        pass  # ignore errors if the cursor is outside the image


if __name__ == '__main__':
    app = App()
    app.mainloop()

It displays an image with the RGB value of the pixel under the mouse pointer under the image (when the mouse pointer is over the image). The image used is this.

Lena.jpg

However, only the upper left quadrant of the image is displayed on the canvas. You can see that in the screenshot below.

screenshot

How can I display the whole image and still have the RGB values of the pixel under the mouse pointer displayed (when the mouse pointer is over the image)?

Ted Ersek
  • 119
  • 4
  • Typo: `self.geometry=('600x600')` should be `self.geometry('600x600')`. Also there is indentation issue in your posted code. – acw1668 Nov 10 '22 at 14:51
  • 1
    Notice that you have fixed the typo, but not the indentation issue. If you fix the indentation issue, you will get the full image as long as the image is not larger than the window (600x600). – acw1668 Nov 10 '22 at 15:38

1 Answers1

1

I can see two possible solutions:

  1. Expand image to fit window
  2. Wrap window around image

To expand image to fit window

dim_x, dim_y = 600, 600
self.img_tk = ImageTk.PhotoImage(self.img_rgb.resize((dim_x, dim_y)))

OR

To wrap window around image

dim_x, dim_y = self.img_rgb.size
self.img_tk = ImageTk.PhotoImage(self.img_rgb)

Both approaches will display the entire image.

Here is the complete code with both options available via select flag.

import tkinter as tk
from PIL import Image, ImageTk
from pathlib import Path

class App(tk.Tk):

    def __init__(self, select = True):
        super().__init__()

        self.img_path = Path('D:\Lenna.jpg')

        self.img = Image.open(self.img_path)
        self.img_rgb = self.img.convert('RGB')

        if select:
            # resize image to fit window

            dim_x, dim_y = 600, 600
            self.img_tk = ImageTk.PhotoImage(self.img_rgb.resize((dim_x, dim_y)))

        else:
            # resize window to fit image

            dim_x, dim_y = self.img_rgb.size
            self.img_tk = ImageTk.PhotoImage(self.img_rgb)

        self.geometry(f'{dim_x}x{dim_y+21}')

        self.canvas = tk.Canvas(self, borderwidth = 0, highlightthickness = 0)
        self.canvas.create_image(0, 0, image = self.img_tk, anchor= tk.NW)

        self.canvas.pack(expand=True, fill=tk.BOTH)

        self.rgb_var = tk.StringVar(self, '0 0 0')
        self.rgb_label = tk.Label(self, textvariable=self.rgb_var)
        self.rgb_label.pack()

        self.bind('<Motion>', lambda e: self.get_rgb(e))


    def get_rgb(self, event):
        x, y = event.x, event.y
        try:
            rgb = self.img_rgb.getpixel((x, y))
            self.rgb_var.set(rgb)
        except IndexError:
            pass  # ignore errors if the cursor is outside the image


if __name__ == '__main__':

    app = App(False)
    app.mainloop()

Everything works as expected when borderwidth and highlightthickness are removed.

Derek
  • 1,916
  • 2
  • 5
  • 15
  • You have used `dim_x` twice in the line `self.geometry(f'{dim_x}x{dim_x+21}')`, it should be `self.geometry(f'{dim_x}x{dim_y+21}')` instead. – acw1668 Nov 15 '22 at 05:54
  • Doh!! Ok fixed it NOW it should work as intended. – Derek Nov 15 '22 at 06:47