使用C ++ / CLI Wrapper返回位图

时间:2016-02-21 19:48:32

标签: c# c++ opencv wrapper

我尝试为OpenCV编写一个CLI包装器,它从给定的OpenCV矩阵返回一个位图。我在包装器中使用带有修复映像的函数来测试它:

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));
}

我的C#代码包含以下用于存储图像的代码:

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

执行代码后,我遇到了这个例外:

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

我该如何解决?这个例外的原因是什么?

2 个答案:

答案 0 :(得分:1)

这不会奏效。因为'框架'当函数返回时,变量超出范围。因此,指针已经死了,你有一个带有垃圾数据指针的GDI对象。

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

  

调用者负责分配和释放scan0参数指定的内存块。但是,在释放相关的Bitmap之前,不应释放内存。

我不确定这个Mat对象是什么,但你得到一维字节行并对预先分配的字节数组(数组^)执行Marshal :: Copy()。

我要么返回从Mat对象创建的数组,要在C#中创建位图,如下所示:

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

或者你可以在C ++代码中这样做,如果你想保持关注点的分离,在C ++中做同样的事情:

auto stream = gcnew MemoryStream(bytes);
auto bitmap = gcnew Bitmap(stream);
delete stream;
return bitmap;

答案 1 :(得分:0)

我在C ++中使用Marshal :: Copy()尝试过它,但仍然遇到同样的问题。我的新功能如下所示:

Bitmap^ GetImage()
{
    Mat mat_frame = imread("Unbenannt.png", 0);
    int size = mat_frame.total() * mat_frame.elemSize();
    int cols = mat_frame.cols;
    int rows = mat_frame.rows;

    array<byte>^ managed_image = gcnew array<byte>(rows * cols);
    Marshal::Copy(IntPtr((void *)mat_frame.data), managed_image, 0, size);
    IntPtr ptr_managed_image = (IntPtr)GCHandle::Alloc(managed_image);
    return gcnew Bitmap(cols, rows, 4 * rows, PixelFormat::Format24bppRgb, ptr_managed_image);
}