Python Forum
[Tkinter] createing a tkinter photoimage from array in python3
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] createing a tkinter photoimage from array in python3
#1
I started with this post and have tried to convert it to python3 - where the tkinter special in pilow has been 'replaced' by 'equivalent' functionality in tkinter.

After much searching and testing I have eventually resorted to writing a file and reading it into the tkinter photoimage object, which is really naff,  but is the only way I have found to make it work.

Surely there is away to pass the data direct to photoimage?

Interestingly my write / read a file approach is still faster than the original version in python 2.7!

Here is my python 3 version of the code:
import tkinter
from PIL import Image
import numpy
import time
import io
#python2 version (original) -> 120fps
#full physical file io and new image each cycle -> 130fps
#reuse PIL Image instead of create new each time -> 160fps

class mainWindow():
    times=1
    timestart=time.clock()
    data=numpy.array(numpy.random.random((400,500))*100,dtype=int)
    theimage = Image.frombytes('L', (data.shape[1],data.shape[0]), data.astype('b').tostring())
    
    def __init__(self):
        self.root = tkinter.Tk()
        self.frame = tkinter.Frame(self.root, width=500, height=400)
        self.frame.pack()
        self.canvas = tkinter.Canvas(self.frame, width=500,height=400)
        self.canvas.place(x=-2,y=-2)
        self.root.after(0,self.start) # INCREASE THE 0 TO SLOW IT DOWN
        self.root.mainloop()
    
    def start(self):
        global data
        global theimage
        self.theimage.frombytes(self.data.astype('b').tobytes())
        self.theimage.save('work.pgm')
        self.photo = tkinter.PhotoImage(file='work.pgm')
        self.canvas.create_image(0,0,image=self.photo,anchor=tkinter.NW)
        self.root.update()
        self.times+=1
        if self.times%33==0:
            print("%.02f FPS"%(self.times/(time.clock()-self.timestart)))
        self.root.after(10,self.start)
        self.data=numpy.roll(self.data,-1,1)

if __name__ == '__main__':
    x=mainWindow()
Reply
#2
Hello,

This code is for python 3. It creates an image in a Label widget. It should work in Canvas with little modification
You will need to change the path to your image

from tkinter import *
from PIL import Image, ImageTk

class TryImage:
    def __init__(self, parent, image_path=None):
        self.image_path = image_path
        self.parent = parent

    def image_to_label(self):
        self.bar = Frame(self.parent, relief=RIDGE, borderwidth=5)
        self.bar.pack(fill=X, side=TOP)

        self.bar.columnconfigure(0, weight=1)
        self.bar.rowconfigure(0, weight=1)

        self.icon = ImageTk.PhotoImage(Image.open(self.image_path))
        self.icon_size = Label(self.bar)
        self.icon_size.image = self.icon
        self.icon_size.configure(image=self.icon)
        self.icon_size.pack(side=LEFT)

if __name__ == '__main__':
    root = Tk()
    ti = TryImage(root, 'images/showroom.png')
    ti.image_to_label()
    root.mainloop()
Larz60+
Reply
#3
Well some more digging and I prised the answer out of a combination of several different places.

Larz60's approach is the way I was already doing it - loading a file, but I eventually found out that the data needs to be in ppm format which is pretty simple to generate. This approach goes twice as fast as writing /  reading a file and isn't really stressing the PC either:

import tkinter
import numpy
import time
#python2 version (original) -> 120fps
#full physical file io and new image each cycle -> 130fps
#reuse PIL Image instead of create new each time -> 160fps
#and... direct image into tkinter using ppm byte array -> 240 fps

class mainWindow():
    times=1
    timestart=time.clock()
    data=numpy.array(numpy.random.random((400,500))*900,dtype=numpy.uint16)
    
    def __init__(self):
        self.root = tkinter.Tk()
        self.frame = tkinter.Frame(self.root, width=500, height=400)
        self.frame.pack()
        self.canvas = tkinter.Canvas(self.frame, width=500,height=400)
        self.canvas.place(x=-2,y=-2)
        xdata = b'P5 500 400 255 ' + self.data.tobytes()
        self.photo = tkinter.PhotoImage(width=500, height=400, data=xdata, format='PPM')
        self.imid = self.canvas.create_image(0,0,image=self.photo,anchor=tkinter.NW)
        self.root.after(1,self.start) # INCREASE THE 0 TO SLOW IT DOWN
        self.root.mainloop()
    
    def start(self):
        global data
        xdata = b'P5 500 400 255 ' + numpy.clip(self.data,0,255).tobytes()
        self.photo = tkinter.PhotoImage(width=500, height=400, data=xdata, format='PPM')
        if True:
            self.canvas.itemconfig(self.imid, image = self.photo)
        else:
            self.canvas.delete(self.imid)
            self.imid = self.canvas.create_image(0,0,image=self.photo,anchor=tkinter.NW)
        self.times+=1
        if self.times%33==0:
            print("%.02f FPS"%(self.times/(time.clock()-self.timestart)))
        self.root.update()
        self.root.after(0,self.start)
        self.data=numpy.roll(self.data,-1,1)

if __name__ == '__main__':
    x=mainWindow()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python3 tkinter radiobutton problem Nick_tkinter 14 5,829 Feb-15-2021, 11:01 PM
Last Post: Nick_tkinter
  Call local variable of previous function from another function with Python3 & tkinter Hannibal 5 4,356 Oct-12-2020, 09:16 PM
Last Post: deanhystad
  question on tkinter canvas PhotoImage gr3yali3n 1 2,105 Sep-05-2020, 12:18 PM
Last Post: Larz60+
  Get the parent label of a ImageTk.PhotoImage delphinis 1 2,362 Aug-02-2020, 03:21 PM
Last Post: deanhystad
  [Tkinter] Tkinter wouldn't work with python3.8.3 shay_xs 2 2,588 May-24-2020, 11:48 PM
Last Post: Larz60+
  [python] [Tkinter] Problem bidding combobox with np.array NEL 3 3,339 Aug-04-2019, 11:07 AM
Last Post: Yoriz
  Gif with PhotoImage Friend 3 5,225 Jul-23-2019, 10:23 PM
Last Post: Friend
  Move PhotoImage dan789 2 2,660 Dec-19-2018, 06:00 PM
Last Post: dan789
  [Tkinter] PhotoImage and Jpeg images. rozen 3 4,534 Jan-07-2018, 08:34 AM
Last Post: Gribouillis

Forum Jump:

User Panel Messages

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