0

I try to write a CLI wrapper for OpenCV, which returns a bitmap from a given OpenCV matrix. I use a function with a fix image inside the wrapper to test it:

Bitmap^ GetImage()
{
    Mat frame = imread("Image.png", 0);
    return gcnew Bitmap(frame.cols, frame.rows, 4 * frame.rows, System::Drawing::Imaging::PixelFormat::Format24bppRgb, IntPtr(frame.data));
}

My C# code contains the following code to store the image back:

Bitmap Test = Wrapper.GetImage();
Test.Save(@"C:\temp\Bla.bmp");

After executing the code, I´ve got this exception:

http://i.stack.imgur.com/79lqW.png

How can I fix it? What is the reason for this exception?

Kampi
  • 1,586
  • 12
  • 23

1 Answers1

1

This won't work. Because the 'frame' variable goes out of scope when the function returns. Thus, the pointer is dead, and you have a GDI object with a pointer to garbage data.

https://msdn.microsoft.com/en-us/library/zy1a2d14(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1

The caller is responsible for allocating and freeing the block of memory specified by the scan0 parameter. However, the memory should not be released until the related Bitmap is released.

I am not sure what this Mat object is, but you get get the one dimensional row of bytes and do a Marshal::Copy() to the pre-allocated byte array (array^).

I would either return this array created from the Mat object and create the bitmap in C# like this:

https://stackoverflow.com/a/21555447/887584

Or you can of course do this in the C++ code if you want to keep separation of concerns, doing the same thing in C++:

auto stream = gcnew MemoryStream(bytes);
auto bitmap = gcnew Bitmap(stream);
delete stream;
return bitmap;
Community
  • 1
  • 1
Emil
  • 376
  • 2
  • 11