Python Forum
Tkinter Pillow Resize Image Looks Choppy While Resizing
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tkinter Pillow Resize Image Looks Choppy While Resizing
#1
I have a frame that stores a label which stores a background image. When I resize the form and the frame resizes, the background image of the label looks really choppy while it's being resized by the function. I was thinking about putting the function on a separate thread because I believe the image might look choppy because of it being on the main thread.

Here's what I've tried:

from tkinter import Tk, Button, Label, Frame
from tkinter import ttk, PhotoImage
import threading
import time
from PIL import Image, ImageTk

class MainWindow(Tk):
    def __init__(self):
        super().__init__()

#create groupbox1 background image for modern look framing
    self.gb1_img = Image.open('imgs/groupbox-1.png')
    self.gb1_img = self.gb1_img.resize((260, 490), Image.Resampling.LANCZOS)
    self.gb1_img = ImageTk.PhotoImage(self.gb1_img)

    self.gb1_container = Frame(self, bg='#333333', width=280)
    self.gb1_container.pack(side='left', fill='y', padx=20, pady=(120, 20))
    self.gb1_container.bind('<Configure>', self.start_resize_gb1)

    self.gb1 = Label(self.gb1_container, image=self.gb1_img, bg='#333333')
    self.gb1.place(x=0, y=0)


def start_resize_gb1(self, e):
    t = threading.Thread(target=self.resize_gb1, args=(e,), daemon=1)
    t.start()


#resize groupbox1 frame image
    def resize_gb1(self, e):
        self.gb1_img1 = Image.open('imgs/groupbox-1.png')
        self.gb1_img1 = self.gb1_img1.resize((e.width, e.height), Image.Resampling.LANCZOS)
        self.gb1_img1 = ImageTk.PhotoImage(self.gb1_img1)
        self.gb1.configure(image=self.gb1_img1)


if __name__ == '__main__':
    app = MainWindow()
    app.title('Main Window')
    app.configure(bg='#333333')

    #center the Main Window:
    w = 1000  # Width
    h = 620  # Height

    app.geometry('%dx%d+%d+%d' % (w, h, x, y))
    app.mainloop()
Is there a way that I can bind the function on it's own thread so that it doesn't look so choppy while resizing?

The error that I keep getting is:

Exception in thread Thread-57 (resize_gb1):
Traceback (most recent call last):
  File "C:\Users\Aaron\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "C:\Users\Aaron\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Aaron\Documents\Python\Project1\testing\MAIN.py", line 92, in resize_gb1
    self.gb1_img1 = ImageTk.PhotoImage(self.gb1_img1)
  File "C:\Users\Aaron\AppData\Roaming\Python\Python310\site-packages\PIL\ImageTk.py", line 143, in __init__
    self.paste(image)
  File "C:\Users\Aaron\AppData\Roaming\Python\Python310\site-packages\PIL\ImageTk.py", line 195, in paste
    im.load()
  File "C:\Users\Aaron\AppData\Roaming\Python\Python310\site-packages\PIL\ImageFile.py", line 268, in load
    self.load_end()
  File "C:\Users\Aaron\AppData\Roaming\Python\Python310\site-packages\PIL\PngImagePlugin.py", line 962, in load_end
    self.fp.read(4)  # CRC
AttributeError: 'NoneType' object has no attribute 'read'
Reply
#2
I don't have your image, but I made a fairly large image (800x800) and resizing is not choppy at all. Even when I opened the file each time, which is wasteful. I included my code if you want to look at it.
import tkinter as tk
from PIL import Image, ImageTk

class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry('360x300')
        frame = tk.Frame(self)
        frame.pack(padx=10, pady=10, expand=True, fill=tk.BOTH)
        frame.bind('<Configure>', self.resize_label)
        self.raw_image = Image.open('test.png')
        self.image = self.raw_image.resize((200, 200), Image.Resampling.LANCZOS)
        self.image = ImageTk.PhotoImage(self.image)
        self.label = tk.Label(frame, image=self.image)
        self.label.place(x=0, y=0)

    def resize_label(self, e):
        size = (e.width, e.height)
        self.image = self.raw_image.resize(size, Image.Resampling.LANCZOS)
        self.image = ImageTk.PhotoImage(self.image)
        self.label["image"] = self.image

if __name__ == '__main__':
    MainWindow().mainloop()
I was able to use a thread to resize the image. This just made drawing the image choppy because the code that resizes the image is no longer synchronized with the window update. You can see that in this version.
import tkinter as tk
from PIL import Image, ImageTk
from threading import Thread

class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry('360x300')
        self.frame = tk.Frame(self)
        self.frame.pack(padx=10, pady=10, expand=True, fill=tk.BOTH)
        self.frame.bind('<Configure>', self.resize_label)
        self.raw_image = Image.open('test.png')
        self.image = self.raw_image.resize((200, 200), Image.Resampling.LANCZOS)
        self.image = ImageTk.PhotoImage(self.image)
        self.label = tk.Label(self.frame, image=self.image)
        self.label.place(x=0, y=0)

    def resize_label(self, e):
        Thread(target=self.resize_image, args=(e.width, e.height)).start()

    def resize_image(self, wide, high):
        self.image = self.raw_image.resize((wide, high), Image.Resampling.LANCZOS)
        self.image = ImageTk.PhotoImage(self.image)
        self.label["image"] = self.image

if __name__ == '__main__':
    MainWindow().mainloop()
I'm not sure what problem you had using threads. The code you posted has errors that prevent it from running, even without resizing the window. Also, your error message does not match anything in the posted code. If you are going to post code and an error message, please post the code that generated the message.

I am also confused by this: "the background image of the label'. A label can have an image, but it cannot have a "background" image. As far as I know there is no way to place other widgets on top of the label's image. Do you know something I don't?
AaronCatolico1 likes this post
Reply
#3
Thanks for your help. I thought that the code I posted was related to the issue. Long day yesterday Doh .
Also, I meant to say that the label enabled me to create a background image for the frame by packing the label into the frame after loading an image into the label.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  rotating image with Tkinter Frankduc 6 6,598 May-21-2022, 03:00 PM
Last Post: Frankduc
Question How to make a button always stay on a point when resizing the window? _ShevaKadu 5 4,227 Nov-04-2020, 03:59 PM
Last Post: deanhystad
  PIL Image / python-resize-image AttributeError sallyjc81 1 5,021 Aug-02-2020, 12:06 AM
Last Post: scidam
  Invert Pillow image colours chesschaser 5 3,814 Jul-11-2020, 02:59 PM
Last Post: chesschaser
  python-resize-image unicode decode error Pedroski55 3 3,500 Apr-21-2020, 10:56 AM
Last Post: Pedroski55
  cv2.resize(...) shutting down processes? DreamingInsanity 1 2,274 Dec-18-2019, 04:06 PM
Last Post: DreamingInsanity
  rotating and resizing objects jenya56 3 2,384 Jul-26-2019, 12:06 AM
Last Post: scidam
  Closing an image opened by Pillow in Window Photo Viewer bigmit37 16 26,460 Aug-11-2017, 03:54 AM
Last Post: grahamnt
  Image : center and resizing vvv 1 12,077 May-14-2017, 03:41 PM
Last Post: Ofnuts

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020