Tkinter画布图像转换

2024-10-02 20:36:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我想有一些过渡,以显示在画布上的图像,我使用Tkinter,我通过图像循环,以显示在画布上,但我需要有一些过渡,同时切换图像。 我正在使用canvasName.create_image方法来显示图像。需要一种方式来顺利地展示它们

这是我的密码:

def Multi_view_rotate():
    window.geometry(str(scr_w)+"x"+str(scr_h)+"+0+0")
    z_out = 20
    
    global timeSleep
    timeSleepVal = int(timeSleep.get())
    global footerPath
    footerPath = footerPath.get()
    #geting director from entry boxes
    global portDirEntry
    portDirEntry = portDirEntry.get()
    
    global colorEntry
    bgcolor = colorEntry.get()
    
    allPaths = getPaths(portDirEntry)
    
    #directory = r"C:\Users\DotNet\Desktop\Ragazinana Data reduced\diashow\4 Random\Landschaft"
    #Get paths
    pathsPrt = allPaths[0]
    pathsLand = allPaths[1]
    #read the image 
    #call the function to get the picture object with new size
    global numOfImagesPort
    global numOfImagesLand
    #footer path
    #footerPath = "C:/Users/DotNet/Desktop/Ragazinana Data reduced/diashow/ragaziana_s.jpg"
    
    #Footer will take 8% of the screen width   
    per_w_footer = cal_per_num(8, scr_w)
    # Footer Image operations
    canvasFoot = Canvas(window,width=per_w_footer, height=scr_h, bg=bgcolor, highlightthickness=1, highlightbackground=bgcolor)
    canvasFoot.grid(row=0, column=0)
    #footerImg = get_img_fit_size(footerPath, scr_h, per_w_footer, True)
    footerImg1 = Image.open(footerPath)
    footerImg2 = footerImg1.transpose(Image.ROTATE_270)
    footerImg3 = footerImg2.resize((int(per_w_footer),int(scr_h)), Image.ANTIALIAS)
    footerImg = ImageTk.PhotoImage(footerImg3)
    footer = canvasFoot.create_image(per_w_footer/2,scr_h/2,anchor=CENTER, image=footerImg)
    
    
    while(numOfImagesPort<=len(pathsPrt)-1 or numOfImagesLand<=len(pathsLand)-1 ):
        
        pathPort = pathsPrt[numOfImagesPort]
        #increase the index to get the next file in the next loop
        numOfImagesPort=numOfImagesPort+1
        #if the next photo is out of bound then assign it to the first index
        if(numOfImagesPort >= len(pathsPrt)):# if total is 5 pic, 1st loop 0 > 6 /reset the loop   
            numOfImagesPort=0
            
        # each image will take as following in percentage
        per_w_imgs_portriate = cal_per_num(42, scr_w)
        per_w_imgs_landscape= cal_per_num(50, scr_w)

        #Create the canvases
        canvasPort = Canvas(window,width=per_w_imgs_portriate, height=scr_h, bg=bgcolor, highlightthickness=10, highlightbackground=bgcolor)
        
        #gird plays the canvas without it the canvas will not work
        canvasPort.grid(row=0, column=1)

        #in order to make the picture fit in the rotated state in the half of the screen
        # we make the get_img_fit_size adjust it to us to that size by providing 
        # screen hight  as a width and half of the screen with as a height
        imgPort = get_img_fit_size(pathPort, scr_h, per_w_imgs_landscape, True)
        
        portImgCanvas = canvasPort.create_image(int(scr_w/4.3),int(scr_h/2),anchor=CENTER, image=imgPort)**
        window.update()
    
        time.sleep(timeSleepVal/2)
        
        # Landscape image 
        pathLand = pathsLand[numOfImagesLand]
        numOfImagesLand = numOfImagesLand+1
        
        if(numOfImagesLand >= len(pathsLand)):
            numOfImagesLand=0
            
        
        canvasLand = Canvas(window,width=per_w_imgs_landscape, height=scr_h, bg=bgcolor, highlightthickness=10, highlightbackground=bgcolor)
        canvasLand.grid(row=0, column=2)
        imgLand = get_img_fit_size(pathLand, scr_h, per_w_imgs_portriate, True)
        landImgCanvas = canvasLand.create_image(int(scr_w/4.5),int(scr_h/2),anchor=CENTER, image=imgLand)
        
                
        window.update()
        time.sleep(timeSleepVal/2)
        
    window.mainloop()

Tags: thetoimagesizegetwindowglobalint
1条回答
网友
1楼 · 发布于 2024-10-02 20:36:49

我认为Tkinter.PhotoImage中没有类似的东西,但您可以通过随机选择像素并将其设置为下一幅图像的颜色值来手动创建“淡入”过渡:

import tkinter, random

root = tkinter.Tk()
c = tkinter.Canvas(root, width=800, height=400)
c.pack()

img_a = tkinter.PhotoImage(file="a.gif")
img_b = tkinter.PhotoImage(file="b.gif")

i = c.create_image(0, 0, image=img_a, anchor="nw")

pixels = [(x, y) for x in range(img_a.width()) for y in range(img_a.height())]
random.shuffle(pixels)

def fade(n=1000):
    global pixels, i
    for _ in range(min(n, len(pixels))):
        x, y = pixels.pop()
        col = "#%02x%02x%02x" % img_b.get(x,y)
        img_a.put(col, (x, y))
    
    c.delete(i)
    i = c.create_image(0, 0, image=img_a, anchor="nw")
    if pixels:
        c.after(1, fade)

fade()
root.mainloop()

这是缓慢的。1ms的after只是为了防止UI冻结(不要在Tkinter中使用whiletime.sleep!)。为了获得更平滑的过渡,您可能会逐渐将所有像素移向下一幅图像中的值,而不是替换像素值,但这将更加缓慢,因为您将在每一步中更改所有像素

我们可以用{}和{}来代替纯粹的tkinter,但速度并不明显快,至少不是我做的方式:

import numpy as np
from PIL import Image, ImageTk
from itertools import islice

...    

arr_a = np.array(Image.open("a.gif").convert("RGB"))
arr_b = np.array(Image.open("b.gif").convert("RGB"))

img = ImageTk.PhotoImage(Image.fromarray(arr_a, mode="RGB"))
i = c.create_image(0, 0, image=img, anchor="nw")

h, w, _ = arr_a.shape
pixels = [(x, y) for x in range(w) for y in range(h)]
random.shuffle(pixels)

def fade(k=0, n=1000):
    global i, img
    X, Y = zip(*islice(pixels, k, k+n))
    arr_a[Y,X] = arr_b[Y,X]
    
    c.delete(i)
    img = ImageTk.PhotoImage(Image.fromarray(arr_a, mode="RGB"))
    i = c.create_image(0, 0, image=img, anchor="nw")
    if k + n < w * h:
        c.after(1, fade, k+n, n)

fade()
root.mainloop()

然而,这也允许我们一次更换整个生产线。效果不是很好,但是速度要快得多(注意改变了nif条件)

...

h, w, _ = arr_a.shape
lines = list(range(h))
random.shuffle(lines)

def fade(k=0, n=10):
    global i, img
    Y = lines[k:k+n]
    arr_a[Y] = arr_b[Y]
    
    ...
    if k + n < h:
        c.after(1, fade, k+n, n)

...

也可以通过简单地不搅乱行(对于列,使用arr_a[:,X] = arr_b[:,X]),轻松地将其转换为垂直或水平幻灯片转换

相关问题 更多 >