利用unsafe代碼在C++和C#之間傳遞圖像

http://blog.csdn.net/halfwet/article/details/7052897

在實際應用中,經常遇到用OpenCV等C++平台的庫來采集圖像,然後傳遞到C#中進行繪制的情況。這時,從C++向C#中傳遞圖像(數組)就成了一個重要的問題。
這裡記錄實驗過的三種方法。
1. 先前一直采用逐像素拷貝的方法:
C++中定義采集圖像函數:

extern "C"  __declspec(dllexport) bool __stdcall  GetBGRMap(BYTE *bgrMap)
{
	bool result = capture->retrieve( bgrImage, CV_CAP_OPENNI_BGR_IMAGE ) ;
	for (int i=0;i<480;i++)
	{
		for (int j = 0;j<640;j++)
		{
			bgrMap[(i*640+j)*4+0] = bgrImage.data[(i*640+j)*3+0];
			bgrMap[(i*640+j)*4+1] = bgrImage.data[(i*640+j)*3+1];
			bgrMap[(i*640+j)*4+2] = bgrImage.data[(i*640+j)*3+2];
			bgrMap[(i*640+j)*4+3] = 255;
		}
	}
	return result;
}

C#中的調用方法為:

 [DllImport("OpencvKinectGrabber.dll", EntryPoint = "GetBGRMap")]
  public static extern bool GetBGRMap(byte[] data);
 
 BGRData = new byte[640 * 480 * 4];
 GetBGRMap(BGRData);

2. 另外還有利用Marshal來進行內存拷貝的方法,但原理應該和上面的方法一致。
3. 上述兩種方法都需要拷貝內存來進行數據傳遞,因為C#使用托管指針,一般不允許對指針的直接操作,因此上兩種方法必須將圖像數據從C++創建的內存區域拷貝到C#創建的內存區域中。但這樣會導致效率下降,尤其是對於大量的數據(如圖像等)。為此,第三種方法采用unsafe代碼在C#中直接獲取C++創建的內存區域的指針。
C++代碼中直接返回圖像的數據:

EXTERN BYTE* __stdcall  GetBGRMap()
{
	bool result = capture->retrieve( bgrImage, CV_CAP_OPENNI_BGR_IMAGE ) ;
	imshow("shit",bgrImage);
	return (BYTE*)bgrImage.data;
}

C#中的調用方法為:

[DllImport("OpencvKinectGrabber.dll", EntryPoint = "GetBGRMap")]
public unsafe static extern byte*  GetBGRMap();

private unsafe void grabImg()
{
	byte* BGRData = GetBGRMap();
	// 在unsafe代碼塊中,可以和c++中一樣對指針進行操作
	// 繪制等操作。。。
}

理論上來說,第三種方法應該是效率最高的,原因就是它沒有進行拷貝內存的操作,而是直接在C#中使用了C++所創建的指針。

你可能感兴趣的:(利用unsafe代碼在C++和C#之間傳遞圖像)