1

Note: You really only need to read the checklist and understand that I want to do this in Tkinter, the rest of the information is for clarification

The complete code is here: https://gist.github.com/SnugBug/1cc5ea67d11487d69aae8549107372ef

I need to be able to manipulate pixels. The goal is to be able to:

  • Control which pixels are drawn first

  • Change the color and position of each pixel

  • Update everything as a whole, so that if a pixel changes the change shows up

  • Clear everything as a whole

The question is, what's the fastest way to check off this list in tkinter? I tried creating an image with PIL, then loading it into tkinter, but I cannot update the image or clear it. The other thing I tried is using tkinter's PhotoImage class, as shown below:

#The function definitions are in the GIST.
#This snippet should be enough information to understand the problem, however.
for i in range(0,3600):
    rot = [0,i,0]
    Tx,Ty,Tz,Zm = [0,0,200,200]
    x,y,z = [10,10,10]
    for m,n in itertools.product(range(-50,50,2),range(-50,50,2)):
        x,y,z = rotate([m,n,0],rot)
        img.put("#ffffff", (int(WIDTH/2 + ((x+Tx)*Zm/(z+Tz))), int(HEIGHT/2 - ((y+Ty)*Zm/(z+Tz)))))
    canvas.update()
    img.blank()
#the confusing math in the `img.put` call is just 3D math

This way is extremely slow. The next way I tried is even slower. It's drawing a line like this: canvas.create_line(x,y,x+1,y+1, ...) Which creates a line of length 1, showing a single pixel. This is excruciatingly slow.

If the separate image method is the fastest, could you include a working snippet in your answer? I cannot figure out the separate image method. I have PIL installed, that's what I was using to attempt it. I lost the python file so I cannot include the code I used to attempt the separate image method.

What I mean by the separate image method: create an image using PIL, drawing on it using PIL, then making that show up on a tkinter screen. This doesn't meet everything on the checklist, however (from what I understand).

If the separate image method is not the fastest, please tell me a way I can check off everything in the checklist some other way. I have a few questions I looked at for help and some sites. They're below

Why is Photoimage put slow? Any of these answers don't work for me because it only creates squares. I need to be able to make any shape.

python tkinter: how to work with pixels? This answer doesn't work because it's too slow.

How to load .bmp file into BitmapImage class Tkinter python This could be helpful

http://zetcode.com/gui/tkinter/drawing/ None of these methods work because I cannot manipulate the order each pixel is drawn, and the color of each individual pixel. If you are familiar with 3D terminology, I need this for a Z-Buffer

If there are any confusions or you need something clarified, please tell me below in the comment section. I am open minded, so if you have a deep understanding of my question and have another idea on how to solve it, I would love to hear it.

  • I mentioned in my earlier answer that you should limit the number of calls to `put` - have you tried that? You can update all the pixels in one large data array and then call `put` just once. Also, why do you say you couldn't clear a PhotoImage? The `blank` method will clear it. – Bryan Oakley Mar 01 '18 at 02:38
  • @Bryan No, I mean I can't clear a PIL image while its being used by tkinter. Also, I don't really know how to limit the calls to put. The array cannot draw pixels in a certain order. I am stuck with doing it pixel by pixel in a for loop. In the array for put, can I include the location of each pixel and not just the color? And does put place these pixels from left to right, top to bottom in that order? – Corpus Shmorpus Mar 01 '18 at 02:43
  • By limiting put, I mean that you manipulate the entire array in memory. Build up a matrix of colors the same size as your image. Change the elements of the matrix in any order you want, and then do a single put to refresh the entire image in one shot. – Bryan Oakley Mar 01 '18 at 02:49
  • @Bryan I can make that work. It’s almost like drawing to a bitmap. If this is the fastest way you could make it into an answer – Corpus Shmorpus Mar 01 '18 at 03:01

1 Answers1

1

If you are using Windows, then the fastest way to put an image on a frame is by ImageWin. The tkinter process of first transforming from PIL image to a tkphotoimage is very slow.

from PIL import Image, ImageWin
from win32gui import GetDC
from tkinter import Tk

root = Tk()
im = Image.open(<file path>)
ImageWin.Dib(im).draw(
        GetDC(ImageWin.HWND(root.winfo_id())), 
        (0,0,100,100)
)