Home > Software design >  Losing quality after resizing an IMage
Losing quality after resizing an IMage

Time:06-20

I try to resize images based on the width of the window. the only problem is that every resize the quality reduce. Here's my code :

from tkinter import *

from PIL import Image, ImageTk

root = Tk()
root.title("Title")
root.geometry("1600x900")
root.minsize(200, 200)
root.configure(background="black")

root.columnconfigure(6)
root.rowconfigure(1)


class Example(Frame):
    def __init__(self, master, *pargs):
        Frame.__init__(self, master, *pargs)


        global root
        self.image = Image.open("img1.png")
        self.img_copy= self.image.copy()

        self.background_image = ImageTk.PhotoImage(self.img_copy)

        self.label1 = Label(root, image=self.background_image, bd='0')
        self.label1.grid(column=1, row=1)
        self.label1.bind('<Configure>', self._resize_image)
    
        self.label2 = Label(root, image=self.background_image, bd='0')
        self.label2.grid(column=2, row=1, sticky="w", padx=5)
        self.label2.bind('<Configure>', self._resize_image)

        self.label3 = Label(root, image=self.background_image, bd='0')
        self.label3.grid(column=3, row=1, sticky="w")
        self.label3.bind('<Configure>', self._resize_image)

        self.label4 = Label(root, image=self.background_image, bd='0')
        self.label4.grid(column=4, row=1, sticky="w", padx=5)
        self.label4.bind('<Configure>', self._resize_image)

        self.label5 = Label(root, image=self.background_image, bd='0')
        self.label5.grid(column=5, row=1, sticky="w")
        self.label5.bind('<Configure>', self._resize_image)

        self.label6 = Label(root, image=self.background_image, bd='0')
        self.label6.grid(column=6, row=1, sticky="w", padx=5)
        root.bind('<Configure>', self._resize_image)

    def _resize_image(self,event):

        new_width = root.winfo_width()
        new_height = root.winfo_height()

        self.img_copy = self.img_copy.resize((int(new_width / 8),int(new_width / 8 * 3 / 2)))

        self.background_image = ImageTk.PhotoImage(self.img_copy)
        self.label1.configure(image =  self.background_image)
        self.label2.configure(image =  self.background_image)
        self.label3.configure(image =  self.background_image)
        self.label4.configure(image =  self.background_image)
        self.label5.configure(image =  self.background_image)
        self.label6.configure(image =  self.background_image)


e = Example(root)
e.place(x=0,y=0)


root.mainloop()

There's a video to show what it looks like : https://imgur.com/a/oE8TPjR

Is there a way to avoid that ?

CodePudding user response:

The reason for the loss in quality is that you don't each time resize from the original image but from the resized one. Change the following part in your code to solve that problem and resize each time from the original image to the new size:

def _resize_image(self,event):

    new_width = root.winfo_width()
    new_height = root.winfo_height()

    self.img_resized = self.img_copy.resize((int(new_width / 8),int(new_width / 8 * 3 / 2)))

    self.background_image = ImageTk.PhotoImage(self.img_resized)

A side effect of resizing a pixel image (not vector graphics) is usually loss of image quality of the resized image compared to the original one no matter how good the resizing program and its algorithm is ( check out a Comparison gallery of image scaling algorithms ). Only enlarging with integer factors like 2x, 3x can preserve the quality of the image. The smaller the resized image compared to the original one the larger is the loss of image quality after enlarging the resized image back to its original size.

PIL allows to choose which kind of resizing algorithm should be applied by specifying the parameter resample ( for example: resample = PIL.Image.LANCZOS ). If you don't provide this parameter, PIL will choose a default one depending on kind of image to scale.

  • Related