天天看點

使用GDI+在記憶體中轉換圖檔類型

  1. 使用GDI+在記憶體中轉換圖檔類型
  2. 作者:盧偉
  3.   微軟新推出的GDI+功能強大,本文僅對圖檔轉換加以讨論,不足之處請大家指出,本人QQ:394777271。
  4. 圖檔類型的轉換支援:bmp、dib、png、gif、jpeg/jpg、tiff、emf等。以下是詳細步驟。
  5.   首先,在StdAfx.h中靜态調用diplus.lib,即由編譯系統完成對DLL的加載,應用程式結束時解除安裝DLL的編碼。如下:
  6. #ifndef ULONG_PTR
  7. #define ULONG_PTR unsigned long*
  8. #include "GdiPlus.h"
  9. using namespace Gdiplus;
  10. #pragma comment(lib, "gdiplus.lib")
  11. #endif
  12. 在類的頭檔案中定義,以下成員變量,用來初始化GDI+的使用和結束使用。
  13. GdiplusStartupInput m_gdiplusStartupInput; 
  14.     ULONG_PTR m_gdiplusToken;
  15. 然後在OnCreate()函數中加入初始化GDI+的函數:
  16. GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);  
  17. 在OnDestroy()函數中加入結束GDI+使用的函數:
  18.     GdiplusShutdown(m_gdiplusToken);
  19. 接着,定義轉換函數:
  20. BOOL MBmpToMImage(CMemFile& cbfBmp, CMemFile& cbfImage, CString strType)
  21. 其中:
  22. CMemFile& cbfBmp表示原位圖檔案;
  23. CMemFile& cbfImage表示轉換後的圖形檔案;
  24. CString strType表示轉換的圖檔類型。
  25. 該函數中主要的處理為以下幾步:
  26.    1. 将原位圖檔案轉換為IStream
  27.    2. 定義Image類執行個體,并使用第1步獲得的IStream初始化
  28.    3. 擷取轉換的圖檔類型的CLSID
  29.    4. 将Image以轉換的圖檔類型儲存到IStream中
  30.    5. 将IStream轉換為CMemFile記憶體檔案(也可為CFile)
  31. 詳細代碼如下:
  32. BOOL MBmpToMImage(CMemFile& cbfBmp, CMemFile& cbfImage, CString strType)
  33. {
  34.     int iBmpSize = cbfBmp.GetLength();
  35.     HGLOBAL hMemBmp = GlobalAlloc(GMEM_FIXED, iBmpSize);
  36.     if (hMemBmp == NULL) return FALSE;
  37.     IStream* pStmBmp = NULL;
  38.     CreateStreamOnHGlobal(hMemBmp, FALSE, &pStmBmp);
  39.     if (pStmBmp == NULL) 
  40.     {
  41.         GlobalFree(hMemBmp);
  42.         return FALSE;
  43.     }
  44.     BYTE* pbyBmp = (BYTE *)GlobalLock(hMemBmp);
  45.     cbfBmp.SeekToBegin();
  46.     cbfBmp.Read(pbyBmp, iBmpSize);
  47.     Image* imImage = NULL;
  48.     imImage = Image::FromStream(pStmBmp, FALSE);
  49.     if (imImage == NULL) 
  50.     {
  51.         GlobalUnlock(hMemBmp);
  52.         GlobalFree(hMemBmp);
  53.         return FALSE;
  54.     }
  55.     USES_CONVERSION;
  56.     CLSID clImageClsid;
  57.     GetImageCLSID(A2W("image/"+strType.GetBuffer(0)), &clImageClsid);
  58.     HGLOBAL hMemImage = GlobalAlloc(GMEM_MOVEABLE, 0);
  59.     if (hMemImage == NULL)
  60.     {
  61.         pStmBmp->Release();
  62.         GlobalUnlock(hMemBmp);
  63.         GlobalFree(hMemBmp);
  64.         if (imImage != NULL) delete imImage;
  65.         return FALSE;
  66.     }
  67.     IStream* pStmImage = NULL;
  68.     CreateStreamOnHGlobal(hMemImage, TRUE, &pStmImage);
  69.     if (pStmImage == NULL)
  70.     {
  71.         pStmBmp->Release();
  72.         GlobalUnlock(hMemBmp);
  73.         GlobalFree(hMemBmp);
  74.         GlobalFree(hMemImage);
  75.         if (imImage != NULL) delete imImage
  76.         return FALSE;
  77.     }   
  78.     imImage->Save(pStmImage, &clJpgClsid);
  79.     if (pStmImage == NULL) 
  80.     {
  81.         pStmBmp->Release();
  82.         pStmImage>Release();
  83.         GlobalUnlock(hMemBmp);
  84.         GlobalFree(hMemBmp);
  85.         GlobalFree(hMemImage;
  86.         if (imImage != NULL) delete imImage;
  87.         return FALSE;
  88.     }
  89.     LARGE_INTEGER liBegin = {0};
  90.     pStmImage->Seek(liBegin, STREAM_SEEK_SET, NULL);
  91.     BYTE* pbyImage = (BYTE *)GlobalLock(hMemImage);
  92.     cbfImage.SeekToBegin();
  93.     cbfImage.Write(pbyImage, GlobalSize(hMemImage));
  94.     if (imImage != NULL) delete imImage;
  95.     pStmBmp->Release();
  96.     pStmImage->Release();
  97.     GlobalUnlock(hMemBmp);
  98.     GlobalUnlock(hMemImage);
  99.     GlobalFree(hMemBmp);
  100.     GlobalFree(hMemImage);
  101.     return TRUE;
  102. }
  103. 最新評論 [發表評論] [文章投稿]  檢視所有評論 推薦給好友 列印
  104. 原文有許多筆誤,更正如下:
  105. 1、GetImageCLSID(A2W("image/"+strType.GetBuffer(0)), &clImageClsid);
  106. ——————————〉
  107. GetImageCLSID(A2W(("image/"+strType).GetBuffer(0)), &clImageClsid);
  108. 2、imImage->Save(pStmImage, &clJpgClsid);
  109. ——————————〉
  110. imImage->Save(pStmImage, &clImageClsid);
  111. 3、if (imImage != NULL) delete imImage
  112. ---------------------〉 少了分号
  113. if (imImage != NULL) delete imImage;
  114. 4、
  115. // GDI+
  116. #ifndef ULONG_PTR
  117. #define ULONG_PTR unsigned long*
  118. #include "GdiPlus.h"
  119. using namespace Gdiplus;
  120. #pragma comment(lib, "gdiplus.lib")
  121. #endif
  122. ---------------------->
  123. #ifndef ULONG_PTR
  124. #define ULONG_PTR unsigned long*
  125. #include "GdiPlus.h"
  126. using namespace Gdiplus;
  127. #pragma comment(lib, "gdiplus.lib")
  128. #include <atlconv.h>
  129. #endif
  130. 建議發文章的人,最好還是要調試一下,否則,會使讀者有些小麻煩。。。 :) ( Mycro 發表于 2005-2-2 11:19:00)
  131. To liutian_32:我現在需要做一個圖檔格式轉換的東東。請問是否可以加入gdiplus.dll這個庫後,你的代碼中的函數救可以直接調用了,因為SDK太大,沒法下載下傳。謝謝!急…… ( andyming 發表于 2004-9-30 10:51:00)
  132. 一年前我就已經用過了. ( 墨林 發表于 2004-8-31 19:39:00)
  133. 這個東西是platform sdk 中gdi+中的示例,通過在微軟的網站下在最新的SDK更新庫的幫助就可以得到. ( 墨林 發表于 2004-8-31 19:39:00)
  134. BOOL GetImageCLSID(const WCHAR* format, CLSID* pCLSID)
  135. {
  136. UINT num = 0;
  137. UINT size = 0;
  138. ImageCodecInfo* pImageCodecInfo = NULL;
  139. GetImageEncodersSize(&num, &size);
  140. if(size == 0){
  141. return FALSE;
  142. }
  143. pImageCodecInfo = (ImageCodecInfo *)(malloc(size));
  144. if(pImageCodecInfo == NULL)
  145. return FALSE;
  146. GetImageEncoders(num, size, pImageCodecInfo); 
  147. // Find for the support of format for image in the windows
  148. for(UINT i = 0; i < num; ++i)
  149. //MimeType: Depiction for the program image  
  150. if( wcscmp(pImageCodecInfo[i].MimeType, format) == 0)
  151. *pCLSID = pImageCodecInfo[i].Clsid; 
  152. free(pImageCodecInfo); 
  153. return TRUE; 
  154. free(pImageCodecInfo); 
  155. return FALSE; 
  156. } ( luwei103 發表于 2004-7-23 13:02:00)
  157. GetEncoderClsid函數是MSDN裡提供的,需要加到你的工程裡 ( luwei103 發表于 2004-7-23 12:49:00)
  158. 為什麼我這裡說GetEncoderCLSID函數未定義呢?需要包含什麼頭檔案?在幫助上發現也沒包含什麼特别檔案呢 ( 村長大人 發表于 2004-7-22 10:45:00)
  159. 轉換圖檔類型當然簡單了,
  160. 1、你必須在你的工程中加入對GDI+的調用即釋放
  161. 2、這裡給出的是在記憶體中實作轉換,MSDN中給的例子是
  162.    通過在硬碟上儲存實作的轉換,在記憶體中相比在硬碟 上實作轉換,效率誰都知道把。如果僅僅是實作圖檔類型的轉換MSDN上面有,誰還會拿來發表阿
  163. 3、相關的Demo我會近期在網站上釋出。 ( luwei103 發表于 2004-7-19 11:20:00)
  164. 更正:
  165.  GetEncoderClsid(L"image/jpeg", &pngClsid);//這裡的圖檔可以是其它格式
  166. 應改為:GetEncoderClsid(L"image/bmp", &pngClsid) ( liutian_32 發表于 2004-7-16 14:56:00)
  167. 如果使用GDI+的話,應該沒有那麼麻煩吧,
  168. void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
  169. {
  170. // TODO: 在此添加消息處理程式代碼和/或調用預設值
  171. Image img(L"d://12.jpg");//這裡的圖檔可以是其它格式
  172. CLSID pngClsid;
  173.            GetEncoderClsid(L"image/jpeg", &pngClsid);//這裡的圖檔可以是其它格式
  174. ,此處轉化為BMP格式
  175. img.Save(L"d://12_0.bmp", &pngClsid, NULL);
  176. CDialog::OnLButtonDown(nFlags, point);
  177. }
  178. GetEncoderClsid函數是MSDN裡提供的,需要加到你的工程裡,真正你要寫的隻有滑鼠事件中的4行代碼,根本不要那麼複雜 ( liutian_32 發表于 2004-7-16 14:55:00)