我嘗試根據視窗的寬度調整影像大小。唯一的問題是每次調整大小質量都會降低。這是我的代碼:
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()
有一個視頻可以展示它的樣子: https ://imgur.com/a/oE8TPjR
有沒有辦法避免這種情況?
uj5u.com熱心網友回復:
質量不斷下降的原因是,您不是每次都從原始影像調整大小,而是從已經調整大小的影像調整大小。
更改代碼中的以下部分以解決該問題并將每次從原始影像調整為新大小:
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)
調整像素影像(不是矢量圖形)大小的副作用通常是與原始影像相比,調整大小影像的影像質量下降,無論調整大小程式及其演算法有多好(查看影像縮放演算法的比較庫) .
只有用 2x、3x 等整數倍放大才能保持影像的質量。與原始影像相比,調整大小的影像越小,將調整大小的影像放大回其原始大小后,影像質量的損失就越大。是的,放大也會在影像中產生扭曲,無法通過將放大的影像縮小回其原始尺寸來消除這些扭曲。
順便說一句:PIL 允許通過指定引數 resample 來選擇應該應用哪種調整大小演算法(例如:)resample = PIL.Image.LANCZOS。如果您不提供此引數,PIL 將根據要縮放的影像型別選擇默認值。
在提供的問題下方,但經過大量修改的代碼展示了三種不同縮放影像方法的副作用:
- 始終從原始影像調整大小
- 使用快速但簡單的方法從縮放的影像調整大小
- 使用復雜的方法從縮放的影像調整大小(慢)
因此您可以自己體驗調整影像大小的方法對影像質量的影響,同時也可以體驗到 tkinter 編程可以在不使用應用程式類的開銷的情況下完成:
from tkinter import Tk, Label, filedialog
from PIL import Image, ImageTk
def resizeLabels(e=None, new_width=None, new_height=None):
global padx, mrgx, mrgy, imgPIL_1, imgPIL_2, imgPIL_3
if new_width is None:
new_width = root.winfo_width()
# if e is not None:
# assert e.width == root.winfo_width()
if new_height is None:
new_height = root.winfo_height()
# if e is not None:
# assert e.height == root.winfo_height()
# Correction of for labels available space size which is less than
# the window size due to grid padding and forced margins:
new_width = new_width - mrgx-3*2*padx
new_height = new_height - mrgy
# Resize always from the original image ( no quality loss ):
imgPIL_0 = imgPIL_1.resize((int(new_width / 3), int(new_height)))
# Resize and use resized image for further resizing. Use two
# resize methods: BOX, and LANCZOS (with reducing_gap optimization):
imgPIL_2 = imgPIL_2.resize((int(new_width / 3), int(new_height)),
resample=Image.BOX)
imgPIL_3 = imgPIL_3.resize((int(new_width / 3), int(new_height)),
resample=Image.LANCZOS, reducing_gap = 3.0)
imgTk_1 = ImageTk.PhotoImage(imgPIL_0)
imgTk_2 = ImageTk.PhotoImage(imgPIL_2)
imgTk_3 = ImageTk.PhotoImage(imgPIL_3)
label_1.config(image=imgTk_1); label_1.image=imgTk_1
label_2.config(image=imgTk_2); label_2.image=imgTk_2
label_3.config(image=imgTk_3); label_3.image=imgTk_3
#:def resizeLabels(...)
eventNo = 0
def processConfigureEvent(e):
global oldWidth, oldHeight, eventNo
newWidth = e.width
newHeight = e.height
# Reduce the amount of resizing operations by invoking actual resize
# only if the amount of window size change exceeds given threshold:
if abs(newWidth newHeight-oldWidth-oldHeight) > 20:
eventNo = 1
print(' eventNo', eventNo, ': ', e, e.x, e.y, e.width, e.height)
oldWidth = newWidth
oldHeight = newHeight
resizeLabels(e=e)
#:def processConfigureEvent(e)
# ----------------------------------------------------------------------
root = Tk()
root.title("Scaling To Window Size")
root.geometry("1024x320")
oldWidth = 1024; oldHeight = 320
root.minsize(256, 80)
root.config(background="black")
root.columnconfigure((0,4), minsize =15) ; mrgx = 30 # root.Grid
root.rowconfigure( (0,2), {'minsize':15}); mrgy = 30 # root.Grid
padx = 15
file = filedialog.askopenfilename(title='Choose an image file',filetypes=[('Image files','*.png *.gif *.jpg *.jpeg'), ('All files', '*.*')])
# file = "img1.png"
imgPIL_1 = Image.open(file)
imgPIL_2 = imgPIL_1.copy()
imgPIL_3 = imgPIL_1.copy()
label_1 = Label(root)
label_1.grid(column=1, row=1, padx=15)
label_2 = Label(root)
label_2.grid(column=2, row=1, padx=15)
label_3= Label(root)
label_3.grid(column=3, row=1, padx=15)
# capturing '<Configure>' event occuring on change in root window
# position or size. Example of printed Configure event object:
# <Configure event x=439 y=388 width=1034 height=332>
root.bind('<Configure>', processConfigureEvent)
# initial resizing of labels with not yet active root window requires
# explicit width/height because root.winfo_width/height doesn't yet
# provide valid root window size values:
resizeLabels(new_width=oldWidth, new_height=oldHeight)
root.mainloop()
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/492989.html
