C# Create a Cognex 8bit image (CogImage8Grey) from an 8bit Grayscale image array (byte[])
Here is some code that shows how to create an 8bit grayscale cognex image (CogImage8Grey) from an 8bit raw image stored as a byte array (byte[]). This type of memory messing is difficult in .NET at the best of times and it’s just a pity the the cognex library doesn’t help much more than it does.
I also have a feeling that the cognex library is doing more copying than it strictly needs to, but in true style its software documentation does not detail if, or when, it copies image data (or much else for that matter!) So I copy the image data from the byte array into a malloc’ed buffer before creating the cognex image.
First we have to define a SafeBuffer through which cognex can free up the allocated memory when it is finished with it, to do this we can derive a class from SafeBuffer like this:
[crayon lang=”csharp”]
///
/// when the object is disposed.
///
class SafeMalloc : SafeBuffer
{
///
///
///The number of bytes to allocate public SafeMalloc(int size) : base(true)
{
this.SetHandle(Marshal.AllocHGlobal(size));
this.Initialize((ulong)size);
}
///
/// memory via FreeHGlobal().
///
///
protected override bool ReleaseHandle()
{
Marshal.FreeHGlobal(this.handle);
return true;
}
///
///
public static implicit operator IntPtr(SafeMalloc h)
{
return h.handle;
}
}
[/crayon]
Its constructor mallocs the memory and when it is disposed ReleaseHandle() is called, and this frees the memory. I also added a cast to IntPtr so that we can pass it into functions that expect an IntPtr.
Now that we have SafeMalloc we can write function to create the cognex image like this:
[crayon lang=”csharp”]
class CognexStuff
{
public ICogImage Convert8BitRawImageToCognexImage(
byte[] imageData, int width, int height)
{
// no padding etc. so size calculation
// is simple.
var rawSize = width * height;
var buf = new SafeMalloc(rawSize);
// Copy from the byte array into the
// previously allocated. memory
Marshal.Copy(imageData, 0, buf, rawSize);
// Create Cognex Root thing.
var cogRoot = new CogImage8Root();
// Initialise the image root, the stride is the
// same as the widthas the input image is byte alligned and
// has no padding etc.
cogRoot.Initialize(width, height, buf, width, buf);
// Create cognex 8 bit image.
var cogImage = new CogImage8Grey();
// And set the image roor
cogImage.SetRoot(cogRoot);
return cogImage;
}
}
[/crayon]
This function allocates memory via SafeMalloc, it then copies the raw image data from the input array into this memory. Then CogImage8Root.Initialize() is called passing in a pointer to this memory. not that in this case the image’s stride is the same as its width. Once the CogImage8Root has been initialised we can create a CogImage8Grey image and set the root via a call to SetRoot()!
They certainly make you work for it!!
If you know that nobody else will be using your image array and are willing to go ‘unsafe'(!) then you could avoid this extra memory copy by pinning the array and getting a pointer to it, you could then pass this pointer directly to the root Initialize() function. In this case you won’t need the SafeMalloc class etc.
Thanks to all on this thread for hints on SafeBuffer!