Jump to content
shineworld

Place image in a TImage

Recommended Posts

Hi all.

 

I'm trying to convert a layout from PySimpleGUI to DelphiVCL.

All works fine but I was not able to put an image in an Image() component programmatically.

 

1] I get a frame from OpenCV VideoCamera cap with:

   self.__cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

   ret, frame = self.__cap.read()
2] I convert the frame to a png image with:

      png_image = cv2.imencode('.png', frame)[1].tobytes()


Now with PySimpleGUI I just update it with: 

   view.window['image_1'].update(data=png_image)

where image_1 = 
sg.Image(filename='', key='image_1', size=(640, 480))

 

With DelphiVCL I've created a image_1 = Image(self) and assigned basic parent and props

but I don't find a way to update the img (an array of bytes with a PNG image inner).

 

Thank you very much for suggestions.

Edited by shineworld

Share this post


Link to post

I was not able to update image content directly from data in memory, but only

passing from a support file:

 

    def __on_timer_update(self, sender):
        # gets frame
        frame = cvc.video_capture_get_frame()
        bmp_image = cv2.imencode('.bmp', frame)[1].tobytes()

        # shows frame image storing it in a support file
        stream = BytesIO(bmp_image)
        with open("output.bmp", "wb") as f:
            f.write(stream.getbuffer())
            f.close()
        self.imgFrame.Picture.LoadFromFile("output.bmp")

This works but I would like to avoid working with files because 60 FPS are

dangerous for SSD devices.


There is some other way to assign the image, in this case a BMP to be simple,
directly to an Image() object using python + DelphiVCL library module ? 

Share this post


Link to post

I have not yet found a fast way to load TImage contents starting from a NumPy array...


this method is enough fast BUT require a file support (at 30FPS SSD will suffer a lot):

        # gets and shows frame image storing it in a support file
        bmp_image = cv2.imencode('.bmp', frame)[1].tobytes()
        stream = BytesIO(bmp_image)
        with open("f:\output_a.bmp", "wb") as f:
            f.write(stream.getbuffer())
            f.close()
        self.imgFrameI.Picture.LoadFromFile("f:\output_a.bmp")

this method access to TImage canvas but is VERY SLOW:

        self.imgFrameI.Picture.Bitmap.SetSize(640, 480)
        canvas = self.imgFrameI.Picture.Bitmap.Canvas
        rgb_im = PIL_Image.fromarray(frame)
        for x in range(640):
            for y in range(480):
                b, g, r = rgb_im.getpixel((x, y))
                rgb = b * 65536 + g * 256 + r
                canvas.SetPixel(x, y, rgb)

There is some other way to set Picture of a Image() object from a image array ?

Share this post


Link to post
On 2/1/2022 at 7:32 PM, pyscripter said:

Demo 29 might be of help.

Initially failed to understand how in Demo29 the use of PIL allowed to place an image in a TImage object.
But slowly I succeeded:

        rgb_im = PIL_Image.fromarray(np.uint8(frame)).convert('RGB')
        self.imgFrameI.Picture.Bitmap.SetSize(rgb_im.width, rgb_im.height)
        dib = PIL_ImageWin.Dib(rgb_im)
        dib.expose(self.imgFrameI.Picture.Bitmap.Canvas.Handle)
        self.imgFrameI.Repaint()

        rgb_im = PIL_Image.fromarray(np.uint8(frame_out)).convert('RGB')
        self.imgFrameO.Picture.Bitmap.SetSize(rgb_im.width, rgb_im.height)
        dib = PIL_ImageWin.Dib(rgb_im)
        dib.expose(self.imgFrameO.Picture.Bitmap.Canvas.Handle)
        self.imgFrameO.Repaint()

Now perfectly works and from 30FPS of PySimpleGUI version, I've reached 89 stable FPS with delphivcl version.
AMAZING how fast delphi vcl is"

 

  • Thanks 2

Share this post


Link to post
On 2/18/2022 at 7:28 PM, shineworld said:

Initially failed to understand how in Demo29 the use of PIL allowed to place an image in a TImage object.
But slowly I succeeded:


        rgb_im = PIL_Image.fromarray(np.uint8(frame)).convert('RGB')
        self.imgFrameI.Picture.Bitmap.SetSize(rgb_im.width, rgb_im.height)
        dib = PIL_ImageWin.Dib(rgb_im)
        dib.expose(self.imgFrameI.Picture.Bitmap.Canvas.Handle)
        self.imgFrameI.Repaint()

        rgb_im = PIL_Image.fromarray(np.uint8(frame_out)).convert('RGB')
        self.imgFrameO.Picture.Bitmap.SetSize(rgb_im.width, rgb_im.height)
        dib = PIL_ImageWin.Dib(rgb_im)
        dib.expose(self.imgFrameO.Picture.Bitmap.Canvas.Handle)
        self.imgFrameO.Repaint()

Now perfectly works and from 30FPS of PySimpleGUI version, I've reached 89 stable FPS with delphivcl version.
AMAZING how fast delphi vcl is"

 

Hello. I'm trying to replicate this code but I'm running into a problem. The line "dib.expose(self.Image1.Picture.Bitmap.Canvas.Handle)" gives the error "line 101, in expose result = self.image.expose(handle)
TypeError: argument 1 must be int, not None". I tried to get the handle via "PIL.ImageWin.HDC(self.Image1.Picture.Bitmap.Canvas)", but also to no avail. The error in this case is "TypeError: argument 1 must be int, not HDC" . Yes, and sorry for my English.

Share this post


Link to post

Hi, could you send project example with unit ? please, thank you

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×