最近做了一个程序要实现在网络中传输图片,这就必须要将图片文件转化为相应的数据,通过几番查找找到了一个方法。以下一一说来。

先说下基本的实现原理,我用到了GDI+的Image类,用它来从磁盘或资源中加载图片,然后将Image转化为IStream ,最后将IStream转化为内存数据LPVOID。从内存数据转化为Image的过程正好相反,先将LPVOID转化为IStream,再从IStream构建Image,并最终显示出来。

以下为所用到的函数,做了一下封装:

 

 
  
  1. inline int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);  
  2. inline BOOL Mem2Hglobal(LPVOID lpBuf, HGLOBAL hGlobal, UINT nSize);  
  3. inline BOOL Stream2Mem(IStream* pstream, void **pOutbuf, UINT* pSize);  
  4.  
  5. inline Image* ImageFromMem(LPVOID lpdata, UINT nSize);  
  6. inline LPVOID Image2Mem(Image* pImage, void** pOutbuf, UINT *pSize, LPCTSTR lpEncoder = _T("p_w_picpath/png"));  
  7.  
  8. BOOL Mem2Hglobal(LPVOID lpBuf, HGLOBAL hGlobal, UINT nSize)  
  9. {  
  10.     LPVOID lpDest = GlobalLock(hGlobal);  
  11.  
  12.     if(lpDest == NULL)  
  13.     {  
  14.         return FALSE;  
  15.     }  
  16.  
  17.     memcpy(lpDest, lpBuf, nSize);  
  18.     GlobalUnlock(hGlobal);  
  19.     return TRUE;  
  20. }  
  21.  
  22. BOOL Stream2Mem(IStream* pstream, void **pOutbuf, UINT* pSize)  
  23. {  
  24.     ULARGE_INTEGER ulnSize;  
  25.     LARGE_INTEGER lnOffset;  
  26.     lnOffset.QuadPart = 0;  
  27.  
  28.     if(pstream->Seek(lnOffset, STREAM_SEEK_END, &ulnSize) != S_OK)  
  29.     {  
  30.         return FALSE;  
  31.     }  
  32.     if(pstream->Seek(lnOffset, STREAM_SEEK_SET, NULL) != S_OK)  
  33.     {  
  34.         return FALSE;  
  35.     }  
  36.  
  37.     *pOutbuf = malloc((size_t)ulnSize.QuadPart);  
  38.     *pSize = (UINT) ulnSize.QuadPart;  
  39.  
  40.     ULONG bytesRead;  
  41.     if(pstream->Read(*pOutbuf, (ULONG)ulnSize.QuadPart, &bytesRead ) != S_OK )  
  42.     {  
  43.         free(*pOutbuf);  
  44.         return FALSE;  
  45.     }  
  46.  
  47.     return TRUE;  
  48. }  
  49.  
  50. LPVOID Image2Mem(Image* pImage, void** pOutbuf, UINT *pSize, LPCTSTR lpEncoder)  
  51. {  
  52.     IStream *pstream = NULL;  
  53.     if( ::CreateStreamOnHGlobal( NULL, TRUE, &pstream ) != S_OK )  
  54.     {  
  55.         return NULL;  
  56.     }  
  57.       
  58.     CLSID jpgClsid;  
  59.     GetEncoderClsid(lpEncoder, &jpgClsid);  
  60.  
  61.     Status state = pImage->Save(pstream, &jpgClsid);  
  62.     if( state != Gdiplus::Ok )  
  63.     {  
  64.         pstream->Release();  
  65.         return NULL;  
  66.     }  
  67.  
  68.     if(!Stream2Mem(pstream, pOutbuf, pSize))  
  69.     {  
  70.         pstream->Release();  
  71.         return NULL;  
  72.     }  
  73.       
  74.     return *pOutbuf;  
  75. }  
  76.  
  77. Image* ImageFromMem(LPVOID lpdata, UINT nSize)  
  78. {  
  79.     IStream *pstream = NULL;  
  80.     HGLOBAL m_hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, nSize);  
  81.  
  82.     if(m_hGlobal == NULL)  
  83.     {  
  84.         return NULL;  
  85.     }  
  86.  
  87.     if(!Mem2Hglobal(lpdata, m_hGlobal, nSize))  
  88.     {  
  89.         ::GlobalFree(m_hGlobal);  
  90.         m_hGlobal = NULL;  
  91.         return NULL;  
  92.     }  
  93.  
  94.     if(::CreateStreamOnHGlobal(m_hGlobal, TRUE, &pstream) != S_OK)  
  95.     {  
  96.         ::GlobalFree(m_hGlobal);  
  97.         m_hGlobal = NULL;  
  98.         return NULL;  
  99.     }  
  100.  
  101.     Image *pImage = Image::FromStream(pstream);  
  102.     pstream->Release();  
  103.     return pImage;  
  104. }  
  105.  
  106. int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)  
  107. {  
  108.     UINT num = 0;  
  109.     UINT size = 0;  
  110.     ImageCodecInfo* pImageCodecInfo = NULL;  
  111.  
  112.     GetImageEncodersSize(&num, &size);  
  113.     if(size == 0)  
  114.     {  
  115.         return -1;  
  116.     }  
  117.  
  118.     pImageCodecInfo = (ImageCodecInfo*)(malloc(size));  
  119.     if(pImageCodecInfo == NULL)  
  120.     {  
  121.         return -1;  
  122.     }  
  123.  
  124.     GetImageEncoders(num, size, pImageCodecInfo);  
  125.  
  126.     for(UINT j = 0; j < num; ++j)  
  127.     {  
  128.         if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )  
  129.         {  
  130.             *pClsid = pImageCodecInfo[j].Clsid;  
  131.             free(pImageCodecInfo);  
  132.             return j;  
  133.         }  
  134.     }  
  135.  
  136.     free(pImageCodecInfo);  
  137.     return -1;  

 

 
  
  1. //从Image转化为LPVOID,调用  
  2. LPVOID Image2Mem(Image* pImage, void** pOutbuf, UINT *pSize, LPCTSTR lpEncoder = _T("p_w_picpath/png"));  
  3.  
  4. //从LPVOID构建Image,调用  
  5. Image* ImageFromMem(LPVOID lpdata, UINT nSize); 

完。