使用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.     
  48.     Image* imImage = NULL;
  49.     imImage = Image::FromStream(pStmBmp, FALSE);
  50.     if (imImage == NULL) 
  51.     {
  52.         GlobalUnlock(hMemBmp);
  53.         GlobalFree(hMemBmp);
  54.         return FALSE;
  55.     }
  56.     USES_CONVERSION;
  57.     CLSID clImageClsid;
  58.     GetImageCLSID(A2W("image/"+strType.GetBuffer(0)), &clImageClsid);
  59.     
  60.     HGLOBAL hMemImage = GlobalAlloc(GMEM_MOVEABLE, 0);
  61.     if (hMemImage == NULL)
  62.     {
  63.         pStmBmp->Release();
  64.         GlobalUnlock(hMemBmp);
  65.         GlobalFree(hMemBmp);
  66.         if (imImage != NULL) delete imImage;
  67.         return FALSE;
  68.     }
  69.     IStream* pStmImage = NULL;
  70.     CreateStreamOnHGlobal(hMemImage, TRUE, &pStmImage);
  71.     if (pStmImage == NULL)
  72.     {
  73.         pStmBmp->Release();
  74.         GlobalUnlock(hMemBmp);
  75.         GlobalFree(hMemBmp);
  76.         GlobalFree(hMemImage);
  77.         if (imImage != NULL) delete imImage
  78.         return FALSE;
  79.     }   
  80.     imImage->Save(pStmImage, &clJpgClsid);
  81.     if (pStmImage == NULL) 
  82.     {
  83.         pStmBmp->Release();
  84.         pStmImage>Release();
  85.         GlobalUnlock(hMemBmp);
  86.         GlobalFree(hMemBmp);
  87.         GlobalFree(hMemImage;
  88.         if (imImage != NULL) delete imImage;
  89.         return FALSE;
  90.     }
  91.     LARGE_INTEGER liBegin = {0};
  92.     pStmImage->Seek(liBegin, STREAM_SEEK_SET, NULL);
  93.     BYTE* pbyImage = (BYTE *)GlobalLock(hMemImage);
  94.     cbfImage.SeekToBegin();
  95.     cbfImage.Write(pbyImage, GlobalSize(hMemImage));
  96.     
  97.     if (imImage != NULL) delete imImage;
  98.     pStmBmp->Release();
  99.     pStmImage->Release();
  100.     GlobalUnlock(hMemBmp);
  101.     GlobalUnlock(hMemImage);
  102.     GlobalFree(hMemBmp);
  103.     GlobalFree(hMemImage);
  104.     return TRUE;
  105. }
  106. 最新评论 [发表评论] [文章投稿]  查看所有评论 推荐给好友 打印
  107. 原文有许多笔误,更正如下:
  108. 1、GetImageCLSID(A2W("image/"+strType.GetBuffer(0)), &clImageClsid);
  109. ——————————〉
  110. GetImageCLSID(A2W(("image/"+strType).GetBuffer(0)), &clImageClsid);
  111. 2、imImage->Save(pStmImage, &clJpgClsid);
  112. ——————————〉
  113. imImage->Save(pStmImage, &clImageClsid);
  114. 3、if (imImage != NULL) delete imImage
  115. ---------------------〉 少了分号
  116. if (imImage != NULL) delete imImage;
  117. 4、
  118. // GDI+
  119. #ifndef ULONG_PTR
  120. #define ULONG_PTR unsigned long*
  121. #include "GdiPlus.h"
  122. using namespace Gdiplus;
  123. #pragma comment(lib, "gdiplus.lib")
  124. #endif
  125. ---------------------->
  126. #ifndef ULONG_PTR
  127. #define ULONG_PTR unsigned long*
  128. #include "GdiPlus.h"
  129. using namespace Gdiplus;
  130. #pragma comment(lib, "gdiplus.lib")
  131. #include <atlconv.h>
  132. #endif
  133. 建议发文章的人,最好还是要调试一下,否则,会使读者有些小麻烦。。。 :) ( Mycro 发表于 2005-2-2 11:19:00)
  134.  
  135. To liutian_32:我现在需要做一个图片格式转换的东东。请问是否可以加入gdiplus.dll这个库后,你的代码中的函数救可以直接调用了,因为SDK太大,没法下载。谢谢!急…… ( andyming 发表于 2004-9-30 10:51:00)
  136.  
  137. 一年前我就已经用过了. ( 墨林 发表于 2004-8-31 19:39:00)
  138.  
  139. 这个东西是platform sdk 中gdi+中的示例,通过在微软的网站下在最新的SDK更新库的帮助就可以得到. ( 墨林 发表于 2004-8-31 19:39:00)
  140.  
  141. BOOL GetImageCLSID(const WCHAR* format, CLSID* pCLSID)
  142. {
  143. UINT num = 0;
  144. UINT size = 0;
  145. ImageCodecInfo* pImageCodecInfo = NULL;
  146. GetImageEncodersSize(&num, &size);
  147. if(size == 0){
  148. return FALSE;
  149. }
  150. pImageCodecInfo = (ImageCodecInfo *)(malloc(size));
  151. if(pImageCodecInfo == NULL)
  152. return FALSE;
  153. GetImageEncoders(num, size, pImageCodecInfo); 
  154. // Find for the support of format for image in the windows
  155. for(UINT i = 0; i < num; ++i)
  156. //MimeType: Depiction for the program image  
  157. if( wcscmp(pImageCodecInfo[i].MimeType, format) == 0)
  158. *pCLSID = pImageCodecInfo[i].Clsid; 
  159. free(pImageCodecInfo); 
  160. return TRUE; 
  161. free(pImageCodecInfo); 
  162. return FALSE; 
  163. } ( luwei103 发表于 2004-7-23 13:02:00)
  164.  
  165. GetEncoderClsid函数是MSDN里提供的,需要加到你的工程里 ( luwei103 发表于 2004-7-23 12:49:00)
  166.  
  167. 为什么我这里说GetEncoderCLSID函数未定义呢?需要包含什么头文件?在帮助上发现也没包含什么特别文件呢 ( 村长大人 发表于 2004-7-22 10:45:00)
  168.  
  169. 转换图片类型当然简单了,
  170. 1、你必须在你的工程中加入对GDI+的调用即释放
  171. 2、这里给出的是在内存中实现转换,MSDN中给的例子是
  172.    通过在硬盘上保存实现的转换,在内存中相比在硬盘 上实现转换,效率谁都知道把。如果仅仅是实现图片类型的转换MSDN上面有,谁还会拿来发表阿
  173. 3、相关的Demo我会近期在网站上发布。 ( luwei103 发表于 2004-7-19 11:20:00)
  174.  
  175. 更正:
  176.  GetEncoderClsid(L"image/jpeg", &pngClsid);//这里的图片可以是其它格式
  177. 应改为:GetEncoderClsid(L"image/bmp", &pngClsid) ( liutian_32 发表于 2004-7-16 14:56:00)
  178.  
  179. 如果使用GDI+的话,应该没有那么麻烦吧,
  180. void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
  181. {
  182. // TODO: 在此添加消息处理程序代码和/或调用默认值
  183. Image img(L"d://12.jpg");//这里的图片可以是其它格式
  184. CLSID pngClsid;
  185.            GetEncoderClsid(L"image/jpeg", &pngClsid);//这里的图片可以是其它格式
  186. ,此处转化为BMP格式
  187. img.Save(L"d://12_0.bmp", &pngClsid, NULL);
  188. CDialog::OnLButtonDown(nFlags, point);
  189. }
  190. GetEncoderClsid函数是MSDN里提供的,需要加到你的工程里,真正你要写的只有鼠标事件中的4行代码,根本不要那么复杂 ( liutian_32 发表于 2004-7-16 14:55:00)
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值