|
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格式)等。
|