2016-02-21 115 views
0

我嘗試爲OpenCV編寫一個CLI包裝器,它從給定的OpenCV矩陣返回一個位圖。我使用的是功能與修復圖像的包裝內,以測試它:用C++/CLI包裝器返回位圖

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

我怎樣才能解決呢?這種例外的原因是什麼?

+0

什麼信息翻譯成英文? –

+0

出現「System.Drawing.dll」中稱爲「System.Runtime.InteropServices.ExternalException」的異常。 附加信息:GDI +中的一般錯誤。 – Kampi

+1

首先嚐試保存到桌面,可能存在權限問題。 –

回答

1

這是行不通的。因爲當函數返回時,'frame'變量超出了範圍。因此,指針已經死了,並且你有一個帶有垃圾數據指針的GDI對象。

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

調用方負責分配和釋放由SCAN0參數指定的內存塊。但是,內存不應釋放,直到相關的位圖被釋放。

我不確定這個Mat對象是什麼,但是你得到了一維的字節行並且對預先分配的字節數組(array ^)執行了Marshal :: Copy()。

我要麼返回這個數組從墊目標創建,創建這樣在C#中的位圖:如果你想保持分離

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

或者你當然可以做到這一點的C++代碼關注,做同樣的事情在C++:

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

從來就與元帥:在C++中複製()嘗試過了,仍然有同樣的問題。我的新功能如下所示:

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

是的,它將與該構造函數相同。按照http://stackoverflow.com/a/21555447/887584中的說明使用構建器 – Emil