Getting pixel data in memoryblock to a viewable image

I’ve got a memoryblock that contains image data from a frame grabber board. The memoryblock contains straight pixel values in either 8 or 16 bit monochrome, unformatted. Is there a quick way to get this into a viewable picture object? We will likely be using the MBS GraphicsMagick plugins as they offer a bunch of transforms and file format conversions we’re going to need anyway.

The frame grabber stores the data very simply - a list of pixel values starting at the top left, ending at the bottom right. So I suppose I could read in each pixel and assemble it from scratch. But if there’s something out there that already does this, I’m happy to not duplicate the effort. Suggestions?

Isn’t that the BMP format? If so, try Picture.FromData.

Try PictureMBS or Einhuger RawBitmap.
(GraphicsMagickMBS might also work).

1 Like

So for an 8 bit image with this grabber, the following code grabs the frame:

Var buffer as Uint64
Var epoc as Uint64 = Integer.FromHex("0x00000000")
Var frameID as UInt16 = Integer.FromHex("0xabcd")
Var grabimage as Integer

buffer = row * col 
Var mb As New MemoryBlock(buffer)
grabimage = GetBufferY8(localHandle,mb,epoc,frameID)
break

Try
  Window1.ImageWell1.Image = Picture.FromData(mb)  
Catch err As UnsupportedFormatException
  ShowMessageBox("Not a supported picture format", "Error")
End Try

ShowMessageBox() is a method in my app to display an error and log it
GetBufferY8() is from the frame grabber dylib, returns an error/success code

And I’m seeing nothing in the image well when I do this, though it’s not failing either.

When I hit the break after the call to GetBufferY8(), and look at the contents of the memory block, all the entries are hexadecimal, but the text area where that’s displayed in the IDE has no scroll, so I can’t look past the first few entries, to see if it looks like sane image data.

The TypeLib plugin that has the RawBitmap and RawBitmapConverter classes is free.

It can create RawBitmap from the Memoryblock.

Big question and what will ultimately determine if it can help you or not is if your map data is compatible with any of the maps the RawBitmap offers.

Now if you find one that fits there then rest is easy, RawBitmapConverter can convert to Xojo picture with one line of code.

1 Like

Thanks! I’ll give that a look tomorrow.

RawBitmap from the memoryblock works, but the formatting of an image this large is about 450ms (where the capture of the frame itself in the frame grabber is 260ms, or around 3fps. And that’s at 8 bit. I haven’t tried 16bit yet.

I’d like to try a few different options to see what’s faster.

have you tried to save the MemoryBlock with a bitmap header in front?
then i would test if paint app can open it correct.
then i would try the same data with
= Picture.FromData(mb)

have you tried to save the MemoryBlock with a bitmap header in front?

Do you mean save it to disk? We’re trying to avoid that, as we have some processing to do - merging three monochrome scans into a single color image, and each frame (at 16bit) will be about 300MB, and aligning the three frames using some pattern matching from OpenCV. Hitting the disk is a big performance issue in this case so we’re trying to keep the three frames in RAM until we absolutely need to do so.

Or are you suggesting something different?

then i would try the same data with
= Picture.FromData(mb)

This just doesn’t work - it doesn’t fail, but as described in this post, the image well doesn’t show anything other than a grey area that looks the same as it did before the frame was captured.

the meaning was saving to disk for a test.
raw data from frame grabber
into
bmp header+data=bitmap file
if this work then you could add a bmp header in front of your memory block, then xojo could load a bitmap from data from memory. it seems you will create a new memory block from overlapping frames too.

Ahh - I see. I’ll give that a go and report back. thanks

from data in xojo speech = file data

Cost of going from MemoryBlock to RawBitmap is zero, since RawBitmap does not copy the memory block but encapsulates it. (Its native internal format is MemoryBlock).
(If you just handed the memory block to the RawBitmap which I assume you did)

The cost you see is basically all in the convert to Xojo Picture in the RawBitmapConverter.ToPicture.

Am not sure there will be any short cuts to that one if you need it to end as Xojo picture then that part will always cost.

Ok. that makes sense. I’m currently using Xojo pictures, just to throw the image into an image well. Right now I’m building a simple test application to test all the basic camera interaction code, but I’m trying to measure things as I go to see where the slowdowns might be.

We will likely end up doing some stuff in OpenCV for the speed that offers, and it may make sense to generate a reduced size image there and send it back to the ImageWell. That’s basically just a preview window, a kind of confidence monitor to make sure things look as expected.

Yea do all the work you possibly can before converting to the Xojo Picture.

Also do not use ImageWell, use Canvas instead, and let it paint in the paint event, just calling Invalidate on it.

1 Like

Ok, I take back what I said about RawBitmap working :grinning: – I had been testing basic grabber/camera connections with a partially setup system, and was getting a black image (to be expected, with the lens cap on). I decided to set up a more realistic arrangement today with some film taped to a light box. And I took the lens cap off.

The result is that i’m getting is this:

The code I’m using is this:

Var rowbytes as integer = row * bpp
Var frame as new RawBitmap( mb , row , col , rowbytes  , RawBitmap.RawBitmapFormat.g )
Var displayImage as Picture = RawBitmapConverter.ToPicture(frame,false)

Window1.Canvas1.Backdrop = displayImage

The image in the frame grabber should be 8bit monochromatic, 14192 x 10640. Using the utilities provided by the frame grabber manufacturer, I get an image. The settings used to take this image are stored on the frame grabber and are the same as in my application. Basically I’m telling the frame grabber - “grab a buffer using the settings already stored in (frame grabber) memory”

sounds like 1 Byte per Pixel
and Bitmap is usually 3 Bytes RGB or 4 Bytes RGBA Or ARGB

can you set your grabber to lowres? should be better to analyze.

Have you mixed up rows & column when creating your RawBitMap?

Good catch - Yes I did! After swapping those I got a black frame, which is an improvement of sorts…

Interesting. I have it at full resolution because the grabber doesn’t do scaling internally and this is a fixed lens at a more or less fixed position from the camera. So we can’t capture the full image, have the board scale it, and export that lower res image. Therefore, you have to select a region of interest in order to get a smaller image, which results in a detail area that’s hard to identify.

Anyway, I just dropped it to 1024x768 - same aspect ratio but a tiny region of interest in the middle of the frame. And there’s an image.

So it occurred to me that the issue might be that the picture is so big, I’m only looking at the black in the corner. I added a .ScaleMBS to the picture display and made it small enough to fit and sure enough - there’s the image!

thanks!

1 Like

great

1 Like
Forum for Xojo Programming Language and IDE. Copyright © 2021 Xojo, Inc.