1、將存儲圖片二進制數據Byte數組,轉為Image類型
(1)Byte[] 存到 IStream 流中(流類似管道):
IStream* m_pView1 = NULL;
//申請一塊全局內存緩沖區
m_hBufView1 = GlobalAlloc(GMEM_MOVEABLE,0);
//將流與內存緩沖區關聯
CreateStreamOnHGlobal(m_hBufView1, TRUE, &m_pView1);
//將Byte[]字節數組寫入到流,其實存到對應關聯的內存
LARGE_INTEGER zero = {0};
ULARGE_INTEGER len = {0};
m_pView1->Seek(zero, STREAM_SEEK_SET, NULL);
m_pView1->Write(字節數組首址,圖片數據字節數,NULL);
//獲得寫入流中數據長度
m_pView1->Seek(zero, STREAM_SEEK_CUR, &len);
DWORD dwlPic1 = len.LowPart;
//重新定位到IStream頭
m_pView1->Seek(zero, STREAM_SEEK_SET, NULL);
if(dwlPic1 !=0)
{
//Byte[]轉為IStream成功,若Byte[]是new出來的,這時Byte[]所占用內存可以釋放
}
(2)將IStream轉為Image
Image* imgV1 = Image::FromStream(m_pView1);
/* Image::FromStream(){
new Image(m_pView1,false)
{
//GpImage* nativeImage 為Image成員變量,存儲圖片數據
//nativeImage進入是野指針,出來時指向存放圖片數據的內存
DllExports::GdipLoadImageFromStream(m_pView1,&nativeImage); //將圖片保存到Image類中nativeImage變量上
};
} */
//Image::FromStream()靜態方法中new了一個Image對象,所以在外部不適用imgV1時,就釋放它
(3)釋放Image資源
delete imgV1;
/* Image::~Image()
{
DllExports::GdipDisposeImage(nativeImage); //釋放nativeImage存儲圖片數據占用的內存
}*/
(4)IStream不使用,釋放內存
if(m_pView1 != NULL)
{
m_pView1->Release();
GlobalFree(m_hBufView1);
m_pView1 = NULL;
}
2、釋放Bitmap資源
在GDI+類庫中對Bitmap類定義。
Bitmap類繼承自Image類,且Bitmap沒有定義析構函數,為默認析構函數
(1)創建Bitmap對象
Bitmap bmp(width,height,PixelFormat24bppRGB);
/* 內部 {
GpBitmap *bitmap = NULL; //GpBitmap繼承自GpImage,存儲圖片數據
//創建一塊可以存儲24位位圖格式的內存,取得內存地址bitmap
lastResult = DllExports::GdipCreateBitmapFromScan0(width,
height,
0,
format,
NULL,
&bitmap);
//將存儲位圖數據的內存地址保存到成員變量 nativeImage 中
SetNativeImage(bitmap); // { this->nativeImage = bitmap }
} */
(2)釋放Bitmap對象
這時我們發現對於Image對象,它有析構函數內存釋放nativeImage所存儲圖片的內存,不會造成內存泄露
而Bitmap沒有定義析構函數,采用默認析構函數,那Bitmap構造出來的內存無法釋放,會造成內存泄露
(當然對於C#、VB對GDI+庫有響應的方法釋放內存)
這時候我們可以參考父類Image的析構函數顯式的釋放nativeImage所占用內存空間
DllExports::GdipDisposeImage(nativeImage);
//nativeImage不是public,可以在Image類中定義一個函數GetnativeImage
小結:
由於nativeImage從Image類中繼承過來的,在Bitmap構造的時候賦值內存首址
所以析構的時候Bitmap析構沒釋放,可能會在Image析構中釋放,這個也可能不會釋放,從而導致使用Bitmap越多,內存占用越大的情況
對於內部申請內存的API或者方法,在外部要記得釋放內存