Home > Net >  How to display RGB data as image in tkinter
How to display RGB data as image in tkinter

Time:12-11

Opening an image file to display in a frame or button in tkinter is simple, but I have images stored in arrays as raw RGB data (for transmission over SPI to a small LCD display). I wish to show this data as a proper image (exactly as processed for the small lcd display) in a frame or button, with tkinter.

I need some steering in how to approach this. Cheers.

CodePudding user response:

You need to convert your array rgb data into an Image object that tkinter knows. For this the best approach is to convert your rgb data to a PIL Image. Depending on how your rgb values are ordered in the array you might need to do some conversions: if rgb data are interleaved (usually the case) or in separate channels/plans, the conversion might fail.

Check for here for converting an array to a pil image. https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.fromarray

Once the conversion to Pil Image is done you can use it in tkinter.

from PIL import Image, ImageTk
import numpy as np
#convert array to PiL Image    
PIL_image = Image.fromarray(np.uint8(your_rgb_array)).convert('RGB')

tk_image = ImageTk.PhotoImage(PIL_image )
label1 = tkinter.Label(image=tk_image )

For displaying the image you should have a look at tk.Canvas: https://www.tutorialspoint.com/python/tk_canvas.htm

CodePudding user response:

Thank you all for your input. I 've been chewing on it for a bit, and now have working code for the task. It takes the image as has been manipulated by numpy or opencv, transforms it to tk format and then shows the original and reduced bitdepth images side by side, with pixel doubling. Here is the snippet with the relevant code:

def nextimg(self):
    f = self.image[self.ptr % self.length]
    self.drawImage(f)
    f = f[...,::-1]
    f = np.repeat(f,2,axis=0)
    f = np.repeat(f,2,axis=1)
    temp=self.size
    self.size=[480,480]
    if self.bpp == 12: g = self.imageConvert_tk12(f)
    elif self.bpp == 16: g = self.imageConvert_tk16(f)
    else: g = self.imageConvert_tk18(f)
    self.button_image1 = ImageTk.PhotoImage(Image.fromarray(np.uint8(f)).convert('RGB'))
    self.button_image2 = ImageTk.PhotoImage(Image.fromarray(np.uint8(g)).convert('RGB'))
    self.button_pic1.configure(image=self.button_image1)
    self.button_pic2.configure(image=self.button_image2)
    self.ptr =1
    self.size=temp

def imageConvert_tk18(self,image):
    x,y = image.shape[0:2]
    arr =np.ndarray((x,y,3))
    arr[...,:] = (np.uint8(image[...,:] >> 2) * 4)
    return arr

def imageConvert_tk16(self,image):
    x,y = image.shape[0:2]
    arr = np.ndarray((x,y,3))
    arr[...,0:3:2] = (np.uint8(image[...,0:3:2] >> 3) * 8)
    arr[...,1] = (np.uint8(image[...,1] >> 2) * 4)
    return arr

def imageConvert_tk12(self,image):
    x,y = image.shape[0:2]
    arr =np.ndarray((x,y,3))
    arr[...,:] = (np.uint8(image[...,:] >> 4) * 16)
    return arr

I also understand a lot more now about lists and arrays. Opencv creates an np.ndarray , which I now understand is a 1-dimensional array (or list in list?) but with a given x-dimensional shape.

Of course I am hoping there might be another solution without having to resort to PIL as intermediary, but if not this will work fine.

Please feel free to suggest improvements to my code!

  • Related