Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tkinter canvas doesn't show entire photo image

Tags:

python

tkinter

I have created a short script to display a photo in a Tkinter canvas element. I size the canvas element to have the same size as the photo, but when I launch the window, I generally only see a small portion of the image, no matter how much I expand the window.

Also when I print out the size of the image, which I am using to set the size of the canvas, this size says (922, 614) whereas when I record mouse clicks on the canvas, the lower-right hand corner is at something like (500, 300). My code is below. What should I change so that the canvas is the same size as the image and fully shows the image?

class AppWindow(Frame):

def __init__(self, parent, list_of_files, write_file):
    Frame.__init__(self, parent)           
    self.parent = parent
    ...
    self.image = None
    self.canvas = None
    self.index = -1
    self.loadImage()
    self.initUI()
    self.resetCanvas()

def initUI(self):
    self.style = Style()
    self.style.theme_use("default")
    self.pack(fill=BOTH, expand=1)
    ...
    self.canvas = Tkinter.Canvas(self, width = self.image.width(), height = self.image.height())   

def loadImage(self):
    self.index += 1
    img = cv2.imread(self.list_of_files[self.index])                       
    img = cv2.resize(img, (0,0), fx = IMAGE_RESIZE_FACTOR, fy = IMAGE_RESIZE_FACTOR)
    b, g, r = cv2.split(img)
    img = cv2.merge((r,g,b))
    im = Image.fromarray(img)
    self.image = ImageTk.PhotoImage(image=im)       

def resetCanvas(self):        
    self.canvas.create_image(0, 0, image=self.image)
    self.canvas.place(x = 0, y = 0, height = self.image.height(), width = self.image.width())

Here is a screenshot showing a photo and how it is presented in the Tkinter canvas:

screenshot

Here's what I have tried so far:

  • Not resizing the image or changing the resizing amount - this doesn't do anything
  • Making the canvas double the size of the image rather than equal to the image, likes so self.canvas = Tkinter.Canvas(self, width = self.image.width()*2, height = self.image.height()*2) This does make the canvas larger (I can tell because I have some drawing functions on the canvas), but the image stays the same small size, not showing the entire image
  • When I display the cv2 format image with cv2.imshow() I see the full image, so it's not cv2 that is cutting off portions of the image.

I realized what I have above is not a complete working example. I've pared the script down, and now running this I still see the same problem:

import Tkinter
import Image, ImageTk
from Tkinter import Tk, BOTH
from ttk import Frame, Button, Style
import cv2
import os
import time
import itertools


IMAGE_RESIZE_FACTOR = .3

class AppWindow(Frame):

    def __init__(self, parent):
        Frame.__init__(self, parent)           
        self.parent = parent
        self.loadImage()
        self.initUI()

    def loadImage(self):
        img = cv2.imread("w_4131.jpg")            
        img = cv2.resize(img, (0,0), fx = IMAGE_RESIZE_FACTOR, fy = IMAGE_RESIZE_FACTOR)
        b, g, r = cv2.split(img)
        img = cv2.merge((r,g,b))
        im = Image.fromarray(img)
        self.image = ImageTk.PhotoImage(image=im)       

    def initUI(self):
        self.style = Style()
        self.style.theme_use("default")
        self.pack(fill=BOTH, expand=1)

        print "width and height of image should be ", self.image.width(), self.image.height()
        self.canvas = Tkinter.Canvas(self, width = self.image.width(), height = self.image.height())
        self.canvas.pack()
        self.canvas.create_image(0, 0, image=self.image)


def main():

    root = Tk()
    root.geometry("250x150+300+300")
    app = AppWindow(root)
    root.mainloop()  


if __name__ == '__main__':

    main()  
like image 495
helloB Avatar asked Sep 03 '15 13:09

helloB


People also ask

Why does Tkinter image not show up if created in a function?

The gist of it is that the image is passed by reference. If the reference is to a local variable, the memory referenced gets reused and the reference becomes stale. The variable storing the image should be in the same scope (has to have the same lifetime) as the Tk gui object it appears on.


1 Answers

When you place an image on a canvas at 0,0, that specifies the location of the center of the image, not the upper-left corner. The image is all there, it's just that you're only seeing the bottom-right corner.

Add anchor="nw" when creating the image for the coordinates to represent the upper-left corner of the image:

self.canvas.create_image(0, 0, image=self.image, anchor="nw")

As for the canvas not being the same size of the image, I'm not seeing that. The image seems to fit the canvas perfectly.

like image 141
Bryan Oakley Avatar answered Oct 01 '22 03:10

Bryan Oakley