Hello

I'm making an GUI app to open a image and zoom it.

This function is used to open the image & display it:

def file_open(self):
                filename =askopenfilename(filetypes=imageTypes)
                image1 = ImageTk.PhotoImage(Image.open(filename))
                self.canvas.config(height=image1.height(), width=image1.width())
                self.canvas.create_image(2, 2, image=image1, anchor=NW)
                self.image = image1
                self.img_zoom(image1) # passing image1 to img_zoom function

The image is zoomed when I click on zoom in on the menu

viewmenu.add_command(label="Zoom In" ,command=self.img_zoom)

This is the function for zoom:

def img_zoom(self,image1):
            width, height = image1.size
            image1.resize((width, height), type)
            scale = 2
            image_resized = image1.resize((int(width*scale), int(height*scale)), Image.ANTIALIAS)
            image1 = ImageTk.PhotoImage(image=image_resized)
            self.canvas.config(height=image1.height(), width=image1.width())
            self.canvas.create_image(2, 2, image=image1, anchor=NW)
            self.image = image1

But I am getting an error saying

return self.func(*args)
TypeError: img_zoom() takes exactly 2 arguments (1 given)

So how exactly do I make image1 available to the zoom function

thank you.

forgot to mention: the above code to resize image was got by googling and seems to have been written by vegaseat in some other forum.

I thought that looked familiar.

Looks like
def img_zoom(self, image1):
also receives an event from the menu click, so try
def img_zoom(self, image1, event):
where event is simply a dummy.

Edited 6 Years Ago by vegaseat: n/a

I thought that looked familiar.

Looks like
def img_zoom(self, image1):
also receives an event from the menu click, so try
def img_zoom(self, image1, event):
where event is simply a dummy.

Hello
It looks like the variables are automatically passed by the 'self' attribute which is passed to img_zoom()

But a new problem has cropped up. When i try to use resize I get the following error:

image_resized = self.image.resize((int(width*scale), int(height*scale)), Image.ANTIALIAS)
AttributeError: PhotoImage instance has no attribute 'resize'

But PhotoImage does have that attribute.

resize doesnt work even if I have it inside the file_open(self).

self.image.resize() is a PIL function and expects self.image to be created via PIL Image not Tkinter Image. It's always a good idea to have namespaces because like in the case of Image it appears in both PIL and Tkinter.

Look closely at the original ...

#!/usr/bin/env python

# display an image using Tkinter and PIL
# ImageTk.PhotoImage() does not have a zoom so use PIL resize

import Tkinter as tk
# ImageTk may need its own install on Ubuntu
from PIL import Image, ImageTk

root = tk.Tk()

# pick an image file you have in your working directory
# using PIL allows Tkinter to read more than just .gif image files
image_file = "LAKE2.jpg"
root.title(image_file)

# load with PIL's Image.open()
image = Image.open(image_file)
width, height = image.size
# image.resize((width, height), type)
scale = 1.5
image_resized = image.resize((int(width*scale), int(height*scale)),
    Image.ANTIALIAS)
# convert to something Tkinter can handle
image_tk = ImageTk.PhotoImage(image=image_resized)

# put the image on a typical widget
label = tk.Label(root, image=image_tk)
label.pack(padx=5, pady=5)

root.mainloop()

Edited 6 Years Ago by vegaseat: code

How do I create the namespace?

I use some other name instead of self.image?

like
pic = ImageTk.PhotoImage(Image.open(filename))
instead of self.image= ImageTk.PhotoImage(Image.open(filename))

and use pic everywhere instead of using self.image?
I tried out this but I'm getting the same error.
How exactly do I create a namespace?

Your problem is with
self.image= ImageTk.PhotoImage(Image.open(filename))
in this case self.image has already been converted to a Tinter image which does not have method resize()

You need to create the PIL image with
img = Image.open(filename)
do your resize on that with
img_resized = img.resize(width*scale, height*scale, Image.ANTIALIAS)
and then convert to a Tkinter image with
self.image = ImageTk.PhotoImage(image=img_resized)
before you can show it with Tkinter.

Your previous issue was the use of self to pass an object to a class method. Look as this simple example ...

class MyClass:
    def __init__(self):
        self.text = "text from MyClass method show_text"
        self.show_text()
    
    def show_text(self):
        print(self.text)

# create an instance of MyClass
mc = MyClass()

The namespace issue might come up if you are using import statements like this
from Tkinter import *
that is for careless folks.

Edited 6 Years Ago by vegaseat: class

Thank you vegaseat, I created a PIL as u told and it works.

So to avoid namespace issues I should be doing something like
import Tkinter as tkin
instead of from Tkinter import *

You have a choice of import statements. Using no namepace is simple to type, but if you import several modules you lose track of where the object came from. Also, if modules have the same named object you will get conflicts.

# import without namespace

from Tkinter import *

root = Tk()

s = "Hello World!"
label = Label(root, text=s, bg='yellow', fg='red')
label.pack(side='left', padx=20, pady=20)

root.mainloop()

This import uses the full module name as namespace and may be a little too much typing. Notice how the namespace is prefixed to the object.

# import with full namespace

import Tkinter

root = Tkinter.Tk()

s = "Hello World!"
label = Tkinter.Label(root, text=s, bg='yellow', fg='red')
label.pack(side='left', padx=20, pady=20)

root.mainloop()

A compromise is to use an abbreviation of the module name, for Tkinter the abbreviation tk is very common.

# import with abbreviated namespace
# pick a recognizable somewhat unique abbreviation

import Tkinter as tk

root = tk.Tk()

s = "Hello World!"
label = tk.Label(root, text=s, bg='yellow', fg='red')
label.pack(side='left', padx=20, pady=20)

root.mainloop()

As a side note, the Python2 module Tkinter.py has become a package named tkinter in Python3. This modified import statement would allow you run your Tkinter code in both versions of Python with a namespace.

# import with abbreviated namespace
# can be used with Python2 and Python3 versions

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

root = tk.Tk()

s = "Hello World!"
label = tk.Label(root, text=s, bg='yellow', fg='red')
label.pack(side='left', padx=20, pady=20)

root.mainloop()

Edited 6 Years Ago by vegaseat: n/a

Comments
Very clearly explained.. u are a good teacher :)

Thank you yet again!!!
That was really clear & helpful. :)

This question has already been answered. Start a new discussion instead.