Advik
Advik

Reputation: 43

Having trouble resizing pictures in tkinter

I'm have couple of images that are looping from a folder on the tkinter window. However, each image has different sizes and I'm not able to resize them in the code itself

import tkinter as tk
import glob
root = tk.Tk()
root.geometry('600x600')

pics = glob.glob("./Images/*.png")
photos = [tk.PhotoImage.resize(20,20)(file=x) for x in pics]
label = tk.Label()
label.photos = photos
label.counter = 0
def cimage():
    label['image'] = label.photos[label.counter%len(label.photos)]
    label.after(3000, cimage)
    label.counter += 1
label.pack()
cimage()

root.mainloop()

Version 2: Also tried the below and got the same error:

import tkinter as tk
import glob
from PIL import Image, ImageTk
root = tk.Tk()
root.geometry('600x600')

pics = glob.glob("./Images/*.png")
photos=pics.resize((20,20),Image.ANTIALIAS)
photosresized = [tk.PhotoImage(file=x) for x in photos]
label = tk.Label()
label.photosresized = photosresized
label.counter = 0
def changeimage():
    label['image'] = label.photosresized[label.counter%len(label.photosresized)]
    label.after(3000, changeimage)
    label.counter += 1
label.pack()
changeimage()

root.mainloop()

Traceback:

Traceback (most recent call last):
  File "/Users/ad/Documents/Python/Project_tkinter/test1.py", line 85, in <module>
    photos = [tk.PhotoImage.resize(20,20)(file=x) for x in pics]
  File "/Users/ad/Documents/Python/Project_tkinter/test1.py", line 85, in <listcomp>
    photos = [tk.PhotoImage.resize(20,20)(file=x) for x in pics]
AttributeError: type object 'PhotoImage' has no attribute 'resize'

Traceback for the second version:

Traceback (most recent call last):
  File "/Users/ad/Documents/Python/Project_tkinter/test1.py", line 86, 
in <module>
    photos=pics.resize((20,20),Image.ANTIALIAS)
AttributeError: 'list' object has no attribute 'resize'

Thanks all appreciated!

Below is the change I made to Joel Toutloff's code to keep the aspect ratio while resizing

basewidth = 20
for i in pics:
    single_image = Image.open(i)
    wpercent = (basewidth / float(single_image.size[0]))
    hsize = int((float(single_image.size[1]) * float(wpercent)))
    changed_size = single_image.resize((basewidth,hsize),Image.ANTIALIAS)
    pid = ImageTk.PhotoImage(single_image.resize((basewidth,hsize),Image.ANTIALIAS))
    photosresized.append(pid)

Upvotes: 0

Views: 88

Answers (2)

Joel Toutloff
Joel Toutloff

Reputation: 484

So glob.glob gives you a list of filenames so you will have to access it with something like "pics[0]", but that will also just give you the filenames and not the actual image. You need to actually load the images into active memory before you can play with them:

import tkinter as tk
import glob
from PIL import Image, ImageTk
root = tk.Tk()
root.geometry('600x600')

pics = glob.glob("./Images/*.png")
photosresized = []
for i in pics:
    single_image = Image.open(i)
    changed_size = single_image.resize((20,20),Image.ANTIALIAS)
    pid = ImageTk.PhotoImage(single_image.resize((20,20),Image.ANTIALIAS))
    photosresized.append(pid)
label = tk.Label()
label.photosresized = photosresized
label.counter = 0
def changeimage():
    label['image'] = label.photosresized[label.counter%len(label.photosresized)]
    label.after(3000, changeimage)
    label.counter += 1
label.pack()
changeimage()

root.mainloop()

This does not change the actual files in any way. It loads them up each one at a time with "Image.open" and then resizes them and saves them into the 'photosresized' list to be used in the animation.

Also note that I changed tk.PhotoImage to be ImageTk.PhotoImage as using things with PIL are preferred.

Upvotes: 1

acw1668
acw1668

Reputation: 46669

You should use PIL.Image.resize() function to resize the image:

import glob
import tkinter as tk
from PIL import Image, ImageTk

root = tk.Tk()
root.geometry('600x600')

label = tk.Label()
label.pack()

label.counter = 0

pics = glob.glob("./Images/*.png")
label.photosresized = [ImageTk.PhotoImage(Image.open(x).resize((20,20),Image.ANTIALIAS)) for x in pics]

def changeimage():
    label['image'] = label.photosresized[label.counter%len(label.photosresized)]
    label.counter += 1
    label.after(3000, changeimage)

changeimage()

root.mainloop()

Upvotes: 1

Related Questions