Convert a C or numpy array to a Tkinter PhotoImage with a minimum number of copies Convert a C or numpy array to a Tkinter PhotoImage with a minimum number of copies numpy numpy

Convert a C or numpy array to a Tkinter PhotoImage with a minimum number of copies


I can reduce it to 1 (maybe 2) copies by using PIL and a Label:

import numpy as npimport tkinter as tkfrom PIL import Image, ImageTka = np.random.randint(low=255, size=(100, 100, 3), dtype=np.uint8) # Originalroot = tk.Tk()img = ImageTk.PhotoImage(Image.fromarray(a)) # First and maybe second copy.lbl = tk.Label(root, image=img)lbl.pack()root.mainloop()

However that's still not mutable. If you want that I think you need to reinvent an image by placing a pixel on the canvas yourself. I did that once with this project and found that the fastest update was a matplotlib animation, which works really well for you since you are already using np arrays.

My code for using a tk.Canvas, a PIL Image(using putpixel()), and matplotlib.


  • you can eliminate the 1st and 2nd copies

You get a numpy.ndarray over arbitrary data with numpy.frombuffer:

shape=(100,100,3)ppm_header = b'P6\n%i %i\n255\n'%(shape[0], shape[1])ppm_bytes = ppm_header + b'\0'*(shape[0]*shape[1]*shape[2])array_image = np.frombuffer(ppm_bytes, dtype=np.uint8, offset=len(ppm_header)).reshape(shape)
  • the 3rd and 4th copies are inevitable (see below), but the 3rd one is discarded right after the call

  • the 5th copy is not actually made (also see below)

  • the drawing stage involves a copy to the screen via the windowing system's drawing API which is also inevitable.


Tcl is a safe, garbage-collected language like Python, and Tcl objects don't support either a "buffer protocol", or using memory for their data that they don't own (though objects can be shared.