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?
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.
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.
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.
Ok, I take back what I said about RawBitmap working – 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.
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”
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!