將影象BYTE(unsigned char)陣列轉換為VARIANT型別
阿新 • • 發佈:2019-02-16
因為近期工作需要完成OCX控制元件同時支援C#與C++呼叫,所以介面設定就會遇上些問題。在需要將圖片的記憶體資料(buffer)傳入控制元件時,如果按照C++慣例,設計介面引數型別為unsigned char*,就會存在被C#識別為ref byte的引數,這樣就只能夠傳遞一個畫素的資料(8bit灰度影象)。
這麼一來,就需要使介面引數型別能夠成功傳遞一個buffer陣列,那麼就想到了VARIANT型別,它可以將陣列封裝起來,包含陣列的維度與長度以及型別資訊。這樣一來就可以滿足要求了。
根據CImage類獲得影象資料(BYTE陣列):
///開啟圖片
CImage img;
img.Load(csName);
/// 獲得影象資料
int pitch = img.GetPitch();
int bytes = abs(pitch) * img.GetHeight();
BYTE * src = (BYTE*)img.GetBits();
BYTE* tempBuffer = new BYTE[bytes];
int sizeLine = abs(pitch);
///這部分影象記憶體的處理將另開一篇博文詳細解釋,此處實現比較粗糙
for ( int line = 0; line < img.GetHeight(); ++line ){
memcpy(tempBuffer + line*sizeLine, src + line*pitch, sizeLine);
}
/// 將影象資料封裝為介面需要的VARIANT型別
VARIANT pImgBuffer;
VariantInit(&pImgBuffer);
SAFEARRAY *psa = NULL;
SAFEARRAYBOUND rgsabound;
rgsabound.cElements = bytes;
rgsabound.lLbound = 0;
psa = SafeArrayCreate(VT_UI1, 1, &rgsabound);
if ( psa == NULL )
return;
BYTE *pBitmapData = NULL;//new BYTE[bytes];(不需要new)
SafeArrayAccessData(psa, (void **)&pBitmapData);
memcpy(pBitmapData, tempBuffer, bytes);
///將SAFEARRAY放入VARIANT中,並設定型別
pImgBuffer.vt = VT_ARRAY | VT_UI1;
SafeArrayCopy(psa, &pImgBuffer.parray);
SafeArrayUnaccessData(psa);
//這裡也就不需要使用delete釋放pBitmapData所指向的空間
//YOUR_INTERFACE(pImgBuffer/*VARIANT*/, img.GetHeight(), img.GetWidth());
if ( tempBuffer )
delete[] tempBuffer;
tempBuffer = NULL;
SafeArrayDestroy(psa);
img.Destroy();
介面內實現:
//VARIANT* pPixArray;(介面引數)
unsigned char* pBuffer = NULL;
SafeArrayAccessData(pPixArray.parray, (void**)&pBuffer);
///此處使用pBuffer所指向的資料
SafeArrayUnaccessData(pPixArray.parray);
HRESULT ret = VariantClear(&pPixArray);