BMP与JPG图片格式的互相转换

近天要用到bmp与jpg之间互想转换,在网上查看了许多资料,如jpeglib,cximage,zlib,最后找到了GDI+利用流来转换,此方法最简单,可以实现在文件->文件,文件->内存,内存->内存,内存->文件保存,对于网络传送图片非常实用,通常320*240*24b的225k的BMP转成JPG后大约15.6K,压缩比15:1.

转换逻辑如下:

1.载入bmp或jpg文件,取得文件数据大小通过GlobalAlloc分配堆内存空间返回的内存句柄作为创建流接口指针的内存句柄,创建流接口.

2.锁定此内存空间,将图片数据memcpy到此空间中

3.通过流创建GDI+中的图片

Image *imImage = NULL;
 imImage = Image::FromStream(pStmBmp, FALSE);

4.取得要编码的GUID详见后代码

5.保存此图到文件或流中

如果只是BMP位图数据则需自已构建位图文件头和位图信息头

代码:

int GetImageCLSID(const  WCHAR*format,  CLSID* pCLSID)  
{//得到格式为format的图像文件的编码值,访问该格式图像的COM组件的GUID值保存在pCLSID中  
 UINT  num = 0;  
 UINT  size = 0;  
 ImageCodecInfo *pImageCodecInfo = NULL;  
 GetImageEncodersSize(&num, &size);  
 if(size == 0)  
  return FALSE;   //编码信息不可用  
 //分配内存  
 pImageCodecInfo = (ImageCodecInfo*)(malloc(size));  
 if(pImageCodecInfo == NULL)  
  return FALSE;   //   分配失败  
 //获得系统中可用的编码方式的所有信息  
 GetImageEncoders(num, size, pImageCodecInfo);  
 //在可用编码信息中查找format格式是否被支持  
 for(UINT i=0; i<num; ++i)  
 {   //MimeType:编码方式的具体描述  
  if(wcscmp(pImageCodecInfo[i].MimeType, format) == 0)  
  {  
   *pCLSID = pImageCodecInfo[i].Clsid;  
   free(pImageCodecInfo);  
   return TRUE;
  }  
 }  
 free(pImageCodecInfo);  
 return   FALSE;  
}

 

void CTest_GDI2Dlg::BMP2JPG()
{
 CFile file("test.bmp", CFile::modeRead);
 int fileLen = file.GetLength();
 HGLOBAL hMemBmp = GlobalAlloc(GPTR, fileLen); 

 BYTE *pbyBmp = (BYTE *)GlobalLock(hMemBmp);
 file.ReadHuge(pbyBmp, fileLen);
 file.Close();

GlobalUnlock(hMemBmp);

//如果只有图位数据信息则要自已构建信息头,下面注释部分测试构建320*240*24b位图文件

/*BITMAPFILEHEADER fileheader;
 BITMAPINFOHEADER infoH;

 memset(&fileheader, 0, sizeof(BITMAPFILEHEADER));
 fileheader.bfType = 19778;//固定为'BM'
 fileheader.bfSize = 320*240*3+54;//构造时注意+54字节头
 fileheader.bfOffBits = 54;
 
 infoH.biSize = sizeof(BITMAPINFOHEADER);
 infoH.biWidth = 320;
 infoH.biHeight = 240;
 infoH.biPlanes = 1;
 infoH.biBitCount = 24;
 infoH.biCompression = BI_RGB;
 infoH.biSizeImage = 320*240*3;
 infoH.biXPelsPerMeter = 0;
 infoH.biYPelsPerMeter = 0;
 infoH.biClrUsed = 0;
 infoH.biClrImportant = 0;

 memcpy(pbyBmp, &fileheader, 14);
 memcpy(pbyBmp+14, &infoH, 40);*/

  //构建指向BMP的流
 IStream *pStmBmp = NULL;
 CreateStreamOnHGlobal(hMemBmp, FALSE, &pStmBmp);

 Image *imImage = NULL;
 imImage = Image::FromStream(pStmBmp, FALSE);

 USES_CONVERSION;
 CLSID clImageClsid;//这里是要转为jpeg格式
 GetImageCLSID(A2W("image/jpeg"),  &clImageClsid);
 int ret = imImage->Save(A2W("1.jpg"), &clImageClsid);//直接保存为文件

//下面可直接保存在流中

 /*HGLOBAL hMemJpg = GlobalAlloc(GMEM_MOVEABLE, 0);

 IStream *pStmImage = NULL;
 CreateStreamOnHGlobal(hMemJpg, FALSE, &pStmImage);
 imImage->Save(pStmImage, &clImageClsid);

 LARGE_INTEGER liBegin = {0};
 pStmImage->Seek(liBegin, STREAM_SEEK_SET, NULL);
 BYTE *pbyjpg = (BYTE *)GlobalLock(hMemJpg);//这里的pbyjpg就是转换后的JPG数据可直接通过网络发送
 
 int Len = GlobalSize(hMemJpg);//这就是转为JPG后文件的大小了
  CFile filejpg("2.jpg", CFile::modeCreate | CFile::modeWrite);
 filejpg.Write(pbyjpg, Len);//这里写成文件和前面直接保存为文件效果一样
 filejpg.Close();

m_pBuf = new char[Len];
 memcpy(m_pBuf, pbyjpg, Len);//可以保存此数据,任你操作哦
 GlobalUnlock(hMemJpg);

GlobalFree(hMemJpg);

 pStmImage->Release();*/
 pStmBmp->Release();
  GlobalFree(hMemBmp);
}

反之JPG转BMP是1个道理,只是中间取得的编码类型不同应该是GetImageCLSID(A2W("image/bmp"),  &clImageClsid);

下面演示接收到网络上的JPG数据转为BMP:m_pBuf假设保存了接收到的JPG数据m_len是此JPG数据大小

void CTest_GDI2Dlg::JPG2BMP()
{
 // TODO: Add your control notification handler code here
 HGLOBAL hMemJpg = GlobalAlloc(GPTR, m_len);
 BYTE *pbyjpg = (BYTE *)GlobalLock(hMemJpg);
 memcpy(pbyjpg, m_pBuf, m_len);
 GlobalUnlock(hMemJpg);

 IStream *pStmJpg = NULL;
 CreateStreamOnHGlobal(hMemJpg, FALSE, &pStmJpg);

 Image *imImage = NULL; //从流中还原图片
 imImage = Image::FromStream(pStmJpg, FALSE);

 USES_CONVERSION;
 CLSID clImageClsid;
 GetImageCLSID(A2W("image/bmp"),  &clImageClsid);//取得BMP编码
 int ret = imImage->Save(A2W("3.bmp"), &clImageClsid);

//可直接保存在流中,任你操作了哦

 /*HGLOBAL hMemBmp = GlobalAlloc(GMEM_MOVEABLE, 0);
 IStream *pStmBmp = NULL;
 CreateStreamOnHGlobal(hMemBmp, FALSE, &pStmBmp);
 imImage->Save(pStmBmp, &clImageClsid);

 int Len = GlobalSize(hMemBmp);//转换后BMP文件大小
 BYTE *pbyBmp = (BYTE *)GlobalLock(hMemBmp);//此数据就可直接调用API画出来了
 CFile filejpg("4.bmp", CFile::modeCreate | CFile::modeWrite);
 filejpg.Write(pbyBmp, Len);
 filejpg.Close();
 GlobalUnlock(hMemBmp);

 pStmBmp->Release();

GlobalFree(hMemBmp);*/
 pStmJpg->Release();
 GlobalFree(hMemJpg);
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值