简体   繁体   中英

Tkinter: format RGB values into string

I am new to Tkinter (and Python) and I would like to find the most efficient way to format RGB values into a string so it can be used with the PhotoImage.put() function.

Let's say I have a Numpy rank 3 array in which the RGB values are stored, the 3rd dimension having a length of 3 for red, green and blue respectively. The most intuitive way to proceed would be:

for i in range(0, n_pixels_x):
    for j in range(0, n_pixels_y):
        hexcode = "#%02x%02x%02x" % (array[i,j,0], array[i,j,1], array[i,j,2])
        img.put(hexcode, (j,i))

Unfortunately, this is way too slow for large images.

As described in the PhotoImage Wiki , it is possible to pass one large string to put() so the function is called only once. Then, I need to efficiently convert my array into such a string, which should be formatted like this (for a 4x2 image):

"{#ff0000 #ff0000 #ff0000 #ff0000} {#ff0000 #ff0000 #ff0000 #ff0000}"

Again, this could easily be done with nested for loops, but I would like to avoid them for efficiency reasons. Is there any way to use join() in order to do what I want?

If needed, I can store the content of my array differently, the only constraint being that I should be able to modify the color values easily.

Edit: After working on this a bit, I found a way to format my values approximately 10 times faster than by using nested loops. Here is the commented piece of code:

# 1. Create RGB array
array = np.zeros((n_pixels_x*n_pixels_y, 3))
array = np.asarray(array, dtype = "uint32")
array[1,:] = [0, 100, 255]

# 2. Create a format string
fmt_str = "{" + " ".join(["#%06x"]*n_pixels_x) + "}"
fmt_str = " ".join([fmt_str]*n_pixels_y)

# 3. Convert RGB values to hex
array_hex = (array[:,0]<<16) + (array[:,1]<<8) + array[:,2]

# 4. Format array
img_str = fmt_str % tuple(array_hex)

For a 640x480 array, steps 3 and 4 take ~0.1s to execute on my laptop (evaluated with timeit.default_timer() ). Using nested loops, it takes between 0.9s and 1.0s.

I would still like to reduce the computation time, but I'm not sure if any improvement is still possible at this point.

I was able to find another way to format my array, and this really seems to be the quickest solution. The solution is to simply use Image and ImageTk to generate an image object directly from the array:

array = np.zeros((height, width, 3), 'uint8')

imageObject = Image.fromarray(array)
img = ImageTk.PhotoImage(image = imageObject, mode = 'RGB'))

This takes approximately 0.02s to run, which is good enough for my needs, and there is no need to use the put() function.

I actually found this answer from another question: How do I convert a numpy array to (and display) an image?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM