如何使用GDI+在缓冲区(内存)中转换图像类型

//datecompress  图片的质量(只有在转换成jpg有效) 

//nSize         图片缓冲区的大小(要转的图片数据大小)

//PicDate       这是一个指针,指向你的图片的

unsigned int size=0;//得到图像大小
BYTE* buffers;//存储图像数据的缓冲


Bitmap *image = CreateBitmapFromMemory(PicDate,nSize);   //把你的图像数据加载入内存


SaveBitmapToMemory(image,(void **)&buffers,&size,CodecIndex,datecompress); //转换成你要的类型,从buffers获取

//说明:CodecIndex取值0-4,分别对应转换为jpg、bmp、gif、png、tiff格式,当为0时,参数datecompress有用,表示转换jpg的质量,取值0-100,数值越小,压缩比越大。
//这里是你的代码

.....

//这里是你的代码
delete image;
delete buffers;

//把这些代码放入声明

Bitmap* CreateBitmapFromMemory(const void *buf, size_t size);   
void* SaveBitmapToMemory(Bitmap *image, void **outbuf, size_t *size, size_t CodecIndex, ULONG quality);
//把这些代码加入到你的源文件最后

int A2U(const char* szA,wchar_t* szU,size_t cnt)
{
 return MultiByteToWideChar (CP_ACP, 0, szA, -1, szU, cnt) ;
}

int     GetEncoderClsid(LPCTSTR szFormat, CLSID* pClsid)  // help
{

 UINT  j;
 UINT  num = 0;          // number of image encoders
 UINT  size = 0;         // size of the image encoder array in bytes
 ImageCodecInfo* pImageCodecInfo = NULL;
 GetImageEncodersSize(&num, &size);
 if(size == 0)
  return -1;  // Failure
 pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
 if(pImageCodecInfo == NULL)
  return -1;  // Failure
 GetImageEncoders(num, size, pImageCodecInfo);
#ifndef UNICODE
 wchar_t  wszFormat[32];
 A2U(szFormat,wszFormat,32);
 for(j = 0; j < num; ++j)
 {
  if( wcscmp(pImageCodecInfo[j].MimeType, wszFormat) == 0 )
#else
 for(j = 0; j < num; ++j)
 {
  if( wcscmp(pImageCodecInfo[j].MimeType, szFormat) == 0 )
#endif
  {
   *pClsid = pImageCodecInfo[j].Clsid;
   free(pImageCodecInfo);
   return j;  // Success
  }
 }
 free(pImageCodecInfo);
 return -1;  // Failure
}

bool mem_to_global(const void *buf, size_t size, HGLOBAL global)
{
 void *dest = GlobalLock( global );
 if( NULL == dest )
 {
  return false;
 }
 memcpy( dest, buf, size );
 GlobalUnlock( global );
 return true;
}

Bitmap* CreateBitmapFromMemory(const void *buf, size_t size)
{
 IStream *stream = NULL;
 global = GlobalAlloc( GMEM_MOVEABLE, size );
 if( NULL == global )
  return NULL;
 /* copy the buf content to the HGLOBAL */
 if( !mem_to_global( buf, size, global ) )
 {
  GlobalFree( global );
  stream->Revert();
  
  return NULL;
 }
 /* get the IStream from the global object */
 if( CreateStreamOnHGlobal( global, true, &stream ) != S_OK )
 {
  GlobalFree( global );
  stream->Revert();
  return NULL;
 }
 /* create the image from the stream */
 Bitmap *image = Bitmap::FromStream( stream, FALSE );
 //stream->Release();
 stream->Revert();
 stream = NULL;
 /* I suppose when the reference count for stream is 0, it will 
 GlobalFree automatically. The Image maintain the object also.*/ 
 return image;
}

bool stream_to_mem(IStream *stream, void **outbuf, size_t *size)
{
 ULARGE_INTEGER ulnSize;
 LARGE_INTEGER lnOffset;
 lnOffset.QuadPart = 0;
 /* get the stream size */
 if( stream->Seek( lnOffset, STREAM_SEEK_END, &ulnSize ) != S_OK )
 {
  return false;
 }
 if( stream->Seek( lnOffset, STREAM_SEEK_SET, NULL ) != S_OK )
 {
  return false;
 }
 /* read it */
 *outbuf = malloc( (size_t)ulnSize.QuadPart );
 *size = (size_t) ulnSize.QuadPart;
 ULONG bytesRead;
 if( stream->Read( *outbuf, (ULONG)ulnSize.QuadPart, &bytesRead ) != S_OK )
 {
  free( *outbuf );
  return false;
 }
 return true;
}

void* SaveBitmapToMemory(Bitmap *image, void **outbuf, size_t *size, size_t CodecIndex, ULONG quality)
//outbuf在函数内malloc内存,因此需free掉
{
 IStream *stream = NULL;
 EncoderParameters encoderParameters,*pencoderParameters=NULL;
 const static TCHAR CodecNames[][11]={
 TEXT("image/jpeg"),
 TEXT("image/bmp"),
 TEXT("image/gif"),
 TEXT("image/png"),
 TEXT("image/tiff")};
 if(CodecIndex>sizeof(CodecNames)/sizeof(CodecNames[0])-1)
  return NULL;
 if(0==CodecIndex)
  pencoderParameters=&encoderParameters;
 if( CreateStreamOnHGlobal( NULL, TRUE, &stream ) != S_OK )
  return NULL;
 CLSID jpgClsid;
 if(-1==GetEncoderClsid(CodecNames[CodecIndex], &jpgClsid ))
  return NULL;
 /* save the image to stream */
 if(quality>100)
  quality=100;
 encoderParameters.Count = 1;
 encoderParameters.Parameter[0].Guid = EncoderQuality;
 encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
 encoderParameters.Parameter[0].NumberOfValues = 1;
 encoderParameters.Parameter[0].Value = &quality;
 Status save_s = image->Save( stream, &jpgClsid, pencoderParameters );
 if( save_s != Ok )
 {
  stream->Release();
  return NULL;
 }
 /* read the stream to buffer */
 if( !stream_to_mem( stream, outbuf, size ) )
 {
  stream->Release();
  return NULL;
 }
 stream->Release();
 GlobalFree(global);
 return *outbuf;
}

 


 至于如何调用GDI+,在我博客中有另外说明

posted @ 2012-06-09 19:26  Jawn  阅读(946)  评论(0编辑  收藏  举报