Miles
Miles

Reputation: 2527

Display a 32 bit unsigned int image with Tkinter and Python 3

If I have a 2D numpy array of 32bit integers, where each refers to a pixels RGBA values(8bit each), generated like so in C++

const Colour *colours = getColourArray();
Uint32 *pixels = getPixelBuffer();
for(size_t i = 0; i < WIDTH * HEIGHT; i++) {
    pixels[i] = (Uint32)(colour[i].r() << 24 | colour[i].g() << 16 | colour[i].b() << 8 | 255);
}

In SDL we can update a texture with the pixels buffer above(where Colour is just a simple RGB struct).

How can such a texture be displayed with Tkinter and Python3?

EDIT: I have access to VTK8 if a VTK renderer can be embedded in a Tkinter window or frame.

Upvotes: 1

Views: 1414

Answers (1)

Novel
Novel

Reputation: 13729

Step 1: make a function that can do the pixel conversion:

def convert(pixel):
    '''convert 32-bit integer to 4 8-bit integers'''
    return list(int(pixel).to_bytes(4, 'big'))

Step 2: convert your 2D array into a 3D array (I'll assume you named the array you have "data").

import numpy as np
new = np.empty((data.size, 4))
old_shape = data.shape
data.shape = -1, # reshape into a 1D array

for i in range(data.size):
    new[i] = convert(data[i])

new.shape = old_shape + (-1,) # reshape into 3D

Step 3: Load the numpy array into an image.

from PIL import Image
img = Image.fromarray(new, mode='RGBA')

Step 4a: If all you want to do is see or save the image then you can use PIL to do that; no tkinter needed.

img.show() # display in your default image viewer
img.save('data.png') # save to disk

Step 4b: If you do need to load it into tkinter then you can use ImageTk.PhotoImage to load it into a Label widget:

from PIL import ImageTk
import tkinter as tk

lbl = tk.Label()
lbl.pimg = ImageTk.PhotoImage(img)
lbl.config(image=lbl.pimg)
lbl.pack()

Upvotes: 1

Related Questions