Chinaunix首页 | 论坛 | 博客
  • 博客访问: 588464
  • 博文数量: 752
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(752)

文章存档

2011年(1)

2008年(751)

我的朋友

分类:

2008-10-13 16:55:21

Image类的序列化
作者:


利用GDI+图形设备接口提供的Image类我们可以很方便地显示JPEG、GIF等文件格式的图片,但美中不足的是Image类未提供序列化数据的功能,如果要将从JPEG、GIF等格式的文件中读取的图片数据保存到我们自己开发的应用程序文档中,并能从文档中读取已经保存的图片数据并正确的显示出来,就必须实现Image类数据的序列化。 假如在你的文档类中有个指向Image类的成员指针变量m_pImage用于显示图片,那么在文档类的序列化函数Serialize(CArchive& ar)中加入以下的代码就能实现m_pImage所指向的图片数据的序列化:
if (ar.IsStoring())
{
	HGLOBAL m_hMem = GlobalAlloc(GMEM_MOVEABLE, 0);
	IStream *pstm=NULL;
	CreateStreamOnHGlobal(m_hMem, TRUE, &pstm);
	CLSID clsid;
	USES_CONVERSION;
	GetCodecClsid(A2W("image/bmp"), &clsid);
	m_pImage->Save(pstm,&clsid,NULL);
	if (pstm==NULL)
		return;
	LARGE_INTEGER liBeggining = { 0 };
	pstm->Seek(liBeggining, STREAM_SEEK_SET, NULL);
	DWORD wTemp=GlobalSize(m_hMem);
	LPBYTE lpData = (LPBYTE)GlobalLock(m_hMem);
	ar << wTemp; 
        ar.Write(lpData,wTemp);
	pstm->Release();
	GlobalUnlock(m_hMem);
}
else
{
	DWORD wTemp;
        ar >> wTemp; 
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, wTemp);
	if (m_hMem == NULL)
		return;
	IStream *pstm=NULL;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
	if (pstm==NULL)
		return;
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	ar.Read(pmem,wTemp);
	if (m_pImage) {
			delete m_pImage;
			m_pImage = NULL;
	   }
	using namespace Gdiplus; 
	m_pImage = Image::FromStream(pstm, FALSE);
	pstm->Release();
	GlobalUnlock(m_hMem);
	//注意此处不能加GlobalFree(m_hMem);否则图片显示不出来。
其中函数GetCodecClsid的实现代码如下:
int GetCodecClsid(const WCHAR* format, CLSID* pClsid)
{
   UINT  num = 0;          // number of image encoders
   UINT  size = 0;         // size of the image encoder array in bytes
   using namespace Gdiplus; 
   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);
   for(UINT j = 0; j < num; ++j)
   {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;
         return j;  // Success
      }    
   } // for
   return -1;  // Failure
} // GetCodecClsid
形参format用以说明图片数据的保存格式,可以取以下一些值:"image/bmp"(位图格式),"image/jpeg"(JPEG格式),"image/gif"(GIF格式)等。
--------------------next---------------------

内存漏洞!

Detected memory leaks!
Dumping objects ->
{260} normal block at 0x003C7738, 1040 bytes long.
 Data: <  |U     s     .> 00 F4 7C 55 04 1A D3 11 9A 73 00 00 F8 1E F3 2E 
Object dump complete.

( sdZym 发表于 2003-11-14 6:21:00)
 
同样, ar >> wTemp 也要删除,因为写文件是长度根本就没有使用ar中保存的那个数值。 ( sdZym 发表于 2003-11-14 4:22:00)
 
存盘后多个4个字节是因为如下代码:
if (ar.IsStoring())
{
  ...
  ar << wTemp; // 多余
  ar.Write(lpData,wTemp);
  ...
} ( sdZym 发表于 2003-11-14 4:17:00)
 
存盘后的文件怎么老是多4个字节? ( herr 发表于 2003-2-4 18:42:00)
 
我想:
pMapImage = new Bitmap(L"Grapes.jpg", TRUE);
为何出错:
error C2660: 'new' : function does not take 3 parameters
而用:
pMapImage = Bitmap::FromFile(L"Grapes.jpg", TRUE);就可以
但 Bitmap::FromFile 内部又是以 new Bitmap(
        filename, 
        useEmbeddedColorManagement) 方式调用的
请问为什么? ( wgwhl 发表于 2002-12-6 19:16:00)
 
示例工程已经修正! ( vckbase 发表于 2002-12-6 18:49:00)
 
不好意思,示例工程中有个小bug,在CGdiplusTestView::OnToolJpg()函数的最后一行少加了Invalidate(); ( hxm 发表于 2002-12-6 9:20:00)
 
Not bad. ( VC70新手 发表于 2002-12-6 5:09:00)
 
.......................................................

--------------------next---------------------

阅读(356) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~