100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > CImage 是基于GDI+的 很老的一篇文章 我很久很久以前看到过的

CImage 是基于GDI+的 很老的一篇文章 我很久很久以前看到过的

时间:2022-12-02 06:50:10

相关推荐

CImage 是基于GDI+的 很老的一篇文章 我很久很久以前看到过的

在许多资料上都说CImage类是基于GDI+的,但是为什么是基于GDI+的呢?

因为使用这个类时,并没有加入#include <gdiplus.h> ,也没有在程序开始和结束时分别写GDI+启动代码GdiplusStartupInput和结束代码GdiplusShutdown

使用这个类时,仅仅需要添加头文件# include<altimage.h>就可以了,比GDI+得使用要简单一些。

而CImage 对图片的处理很类似GDI+ ,其内部是不是封装了GDI+呢? 幸好,CImage类 是源码公开的,我们可以研究其源码,以便加深理解。

首先,看看altimage.h头文件

#ifndef__ATLIMAGE_H__ #define__ATLIMAGE_H__ #pragmaonce #include<atldef.h> #include<atlbase.h> #include<atlstr.h> #include<atlsimpcoll.h> #include<atltypes.h> #ifndef_ATL_NO_PRAGMA_WARNINGS #pragmawarning(push) #pragmawarning(disable:4820)//paddingaddedaftermember #endif//!_ATL_NO_PRAGMA_WARNINGS #pragmawarning(push,3) #pragmapush_macro("new") #undefnew #include<gdiplus.h>//注意这里:添加了GDI+得头文件 #pragmapop_macro("new") #pragmawarning(pop) #include<shlwapi.h> #ifndef_ATL_NO_DEFAULT_LIBS #pragmacomment(lib,"gdi32.lib") #pragmacomment(lib,"shlwapi.lib") #pragmacomment(lib,"gdiplus.lib") #ifWINVER>=0x0500 #pragmacomment(lib,"msimg32.lib") #endif//WINVER>=0x0500 #endif//!_ATL_NO_DEFAULT_LIBS #pragmapack(push,_ATL_PACKING) #ifndef __ATLIMAGE_H__#define __ATLIMAGE_H__#pragma once#include <atldef.h>#include <atlbase.h>#include <atlstr.h>#include <atlsimpcoll.h>#include <atltypes.h>#ifndef _ATL_NO_PRAGMA_WARNINGS#pragma warning (push)#pragma warning(disable : 4820) // padding added after member#endif //!_ATL_NO_PRAGMA_WARNINGS#pragma warning( push, 3 )#pragma push_macro("new")#undef new#include <gdiplus.h> // 注意这里:添加了GDI+得头文件#pragma pop_macro("new")#pragma warning( pop )#include <shlwapi.h>#ifndef _ATL_NO_DEFAULT_LIBS#pragma comment(lib, "gdi32.lib")#pragma comment(lib, "shlwapi.lib")#pragma comment(lib, "gdiplus.lib")#if WINVER >= 0x0500#pragma comment(lib, "msimg32.lib")#endif // WINVER >= 0x0500#endif // !_ATL_NO_DEFAULT_LIBS#pragma pack(push, _ATL_PACKING)

上面包含了GDI+得头文件

再来看CImage的定义:

classCImage{private:classCDCCache{public:CDCCache()throw();~CDCCache()throw();HDCGetDC()throw();voidReleaseDC(HDC)throw();private:HDCm_ahDCs[CIMAGE_DC_CACHE_SIZE];};classCInitGDIPlus{public:CInitGDIPlus()throw();~CInitGDIPlus()throw();boolInit()throw();voidReleaseGDIPlus()throw();voidIncreaseCImageCount()throw();voidDecreaseCImageCount()throw();private:ULONG_PTRm_dwToken;CRITICAL_SECTIONm_sect;LONGm_nCImageObjects;}; class CImage{private: class CDCCache { public: CDCCache() throw(); ~CDCCache() throw(); HDC GetDC() throw(); void ReleaseDC( HDC ) throw(); private: HDC m_ahDCs[CIMAGE_DC_CACHE_SIZE]; }; class CInitGDIPlus { public: CInitGDIPlus() throw(); ~CInitGDIPlus() throw(); bool Init() throw(); void ReleaseGDIPlus() throw(); void IncreaseCImageCount() throw(); void DecreaseCImageCount() throw(); private: ULONG_PTR m_dwToken; CRITICAL_SECTION m_sect; LONG m_nCImageObjects; };

staticCInitGDIPluss_initGDIPlus; static CInitGDIPlus s_initGDIPlus; staticCDCCaches_cache; static CDCCache s_cache;

它定义了两个类成员变量: 其中CInitGDIPlus 是负责GDI+的启动和释放

我们再看一下,这个成员类的Init()方法:

inlineboolCImage::CInitGDIPlus::Init()throw(){EnterCriticalSection(&m_sect);boolfRet=true;if(m_dwToken==0){Gdiplus::GdiplusStartupInputinput;Gdiplus::GdiplusStartupOutputoutput;Gdiplus::Statusstatus=Gdiplus::GdiplusStartup(&m_dwToken,&input,&output);//启动GDI+ if(status!=Gdiplus::Ok)fRet=false;}LeaveCriticalSection(&m_sect);returnfRet;} inline bool CImage::CInitGDIPlus::Init() throw(){ EnterCriticalSection(&m_sect); bool fRet = true; if( m_dwToken == 0 ) { Gdiplus::GdiplusStartupInput input; Gdiplus::GdiplusStartupOutput output; Gdiplus::Status status = Gdiplus::GdiplusStartup( &m_dwToken, &input, &output ); //启动GDI+ if( status != Gdiplus::Ok ) fRet = false; } LeaveCriticalSection(&m_sect); return fRet;}

也就是说 使用这个函数 启动GDI+

再看下一个函数:

inlinevoidCImage::CInitGDIPlus::ReleaseGDIPlus()throw(){EnterCriticalSection(&m_sect);if(m_dwToken!=0){Gdiplus::GdiplusShutdown(m_dwToken);}m_dwToken=0;LeaveCriticalSection(&m_sect);} inline void CImage::CInitGDIPlus::ReleaseGDIPlus() throw(){ EnterCriticalSection(&m_sect); if( m_dwToken != 0 ) { Gdiplus::GdiplusShutdown( m_dwToken ); } m_dwToken = 0; LeaveCriticalSection(&m_sect);}

也就是说, 使用这一个函数,用来关闭GDI+

到此,我们便可知道,CImage类是基于GDI+的,但是我们还不知道CImage 对象是不是在初始化时就启动了GDI+?如果不是,那什么时候才启动GDI+呢?

为解决这个疑惑,我们查看CImage 构造函数

inlineCImage::CImage()throw():m_hBitmap(NULL),m_pBits(NULL),m_hDC(NULL),m_nDCRefCount(0),m_hOldBitmap(NULL),m_nWidth(0),m_nHeight(0),m_nPitch(0),m_nBPP(0),m_iTransparentColor(-1),m_bHasAlphaChannel(false),m_bIsDIBSection(false){s_initGDIPlus.IncreaseCImageCount();} inline CImage::CImage() throw() : m_hBitmap( NULL ), m_pBits( NULL ), m_hDC( NULL ), m_nDCRefCount( 0 ), m_hOldBitmap( NULL ), m_nWidth( 0 ), m_nHeight( 0 ), m_nPitch( 0 ), m_nBPP( 0 ), m_iTransparentColor( -1 ), m_bHasAlphaChannel( false ), m_bIsDIBSection( false ){ s_initGDIPlus.IncreaseCImageCount();}

inlinevoidCImage::CInitGDIPlus::IncreaseCImageCount()throw(){EnterCriticalSection(&m_sect);m_nCImageObjects++;LeaveCriticalSection(&m_sect);} inline void CImage::CInitGDIPlus::IncreaseCImageCount() throw(){ EnterCriticalSection(&m_sect); m_nCImageObjects++; LeaveCriticalSection(&m_sect);}

由此可见,构造函数并没有启动GDI+

也就是说定义 CImage image; 这个image变量时,并没有启动GDI+

我们继续查找:

inlineboolCImage::InitGDIPlus()throw(){boolbSuccess=s_initGDIPlus.Init();return(bSuccess);} inline bool CImage::InitGDIPlus() throw(){ bool bSuccess = s_initGDIPlus.Init(); return( bSuccess );}

CImage使用InitGDIPlus() 来初始化GDI+

因此我们查找InitGDIPlus() 的所有引用 ,发现以下函数:

inlineHRESULTCImage::GetImporterFilterString(CSimpleString&strImporters,CSimpleArray<GUID>&aguidFileTypes,LPCTSTRpszAllFilesDescription/*=NULL*/,DWORDdwExclude/*=excludeDefaultLoad*/,TCHARchSeparator/*='|'*/){if(!InitGDIPlus()){return(E_FAIL);}UINTnCodecs;UINTnSize;Gdiplus::Statusstatus;Gdiplus::ImageCodecInfo*pCodecs;status=Gdiplus::GetImageDecodersSize(&nCodecs,&nSize);USES_ATL_SAFE_ALLOCA;pCodecs=static_cast<Gdiplus::ImageCodecInfo*>(_ATL_SAFE_ALLOCA(nSize,_ATL_SAFE_ALLOCA_DEF_THRESHOLD));if(pCodecs==NULL)returnE_OUTOFMEMORY;status=Gdiplus::GetImageDecoders(nCodecs,nSize,pCodecs);BuildCodecFilterString(pCodecs,nCodecs,strImporters,aguidFileTypes,pszAllFilesDescription,dwExclude,chSeparator);return(S_OK);}inlineHRESULTCImage::GetExporterFilterString(CSimpleString&strExporters,CSimpleArray<GUID>&aguidFileTypes,LPCTSTRpszAllFilesDescription/*=NULL*/,DWORDdwExclude/*=excludeDefaultSave*/,TCHARchSeparator/*='|'*/){if(!InitGDIPlus()){return(E_FAIL);}UINTnCodecs;UINTnSize;Gdiplus::Statusstatus;Gdiplus::ImageCodecInfo*pCodecs;status=Gdiplus::GetImageDecodersSize(&nCodecs,&nSize);USES_ATL_SAFE_ALLOCA;pCodecs=static_cast<Gdiplus::ImageCodecInfo*>(_ATL_SAFE_ALLOCA(nSize,_ATL_SAFE_ALLOCA_DEF_THRESHOLD));if(pCodecs==NULL)returnE_OUTOFMEMORY;status=Gdiplus::GetImageDecoders(nCodecs,nSize,pCodecs);BuildCodecFilterString(pCodecs,nCodecs,strExporters,aguidFileTypes,pszAllFilesDescription,dwExclude,chSeparator);return(S_OK);} inline HRESULT CImage::GetImporterFilterString( CSimpleString& strImporters, CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription /* = NULL */, DWORD dwExclude /* = excludeDefaultLoad */, TCHAR chSeparator /* = '|' */ ){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nCodecs; UINT nSize; Gdiplus::Status status; Gdiplus::ImageCodecInfo* pCodecs; status = Gdiplus::GetImageDecodersSize( &nCodecs, &nSize ); USES_ATL_SAFE_ALLOCA; pCodecs = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nSize, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pCodecs == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageDecoders( nCodecs, nSize, pCodecs ); BuildCodecFilterString( pCodecs, nCodecs, strImporters, aguidFileTypes, pszAllFilesDescription, dwExclude, chSeparator ); return( S_OK );}inline HRESULT CImage::GetExporterFilterString( CSimpleString& strExporters, CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription /* = NULL */, DWORD dwExclude /* = excludeDefaultSave */, TCHAR chSeparator /* = '|' */ ){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nCodecs; UINT nSize; Gdiplus::Status status; Gdiplus::ImageCodecInfo* pCodecs; status = Gdiplus::GetImageDecodersSize( &nCodecs, &nSize ); USES_ATL_SAFE_ALLOCA; pCodecs = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nSize, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pCodecs == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageDecoders( nCodecs, nSize, pCodecs ); BuildCodecFilterString( pCodecs, nCodecs, strExporters, aguidFileTypes, pszAllFilesDescription, dwExclude, chSeparator ); return( S_OK );}

inlineHRESULTCImage::Load(IStream*pStream)throw(){if(!InitGDIPlus()){return(E_FAIL);}Gdiplus::BitmapbmSrc(pStream);if(bmSrc.GetLastStatus()!=Gdiplus::Ok){return(E_FAIL);}return(CreateFromGdiplusBitmap(bmSrc));}inlineHRESULTCImage::Load(LPCTSTRpszFileName)throw(){if(!InitGDIPlus()){return(E_FAIL);}Gdiplus::BitmapbmSrc((CT2W)pszFileName);if(bmSrc.GetLastStatus()!=Gdiplus::Ok){return(E_FAIL);}return(CreateFromGdiplusBitmap(bmSrc));} inline HRESULT CImage::Load( IStream* pStream ) throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } Gdiplus::Bitmap bmSrc( pStream ); if( bmSrc.GetLastStatus() != Gdiplus::Ok ) { return( E_FAIL ); } return( CreateFromGdiplusBitmap( bmSrc ) );}inline HRESULT CImage::Load( LPCTSTR pszFileName ) throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } Gdiplus::Bitmap bmSrc( (CT2W)pszFileName ); if( bmSrc.GetLastStatus() != Gdiplus::Ok ) { return( E_FAIL ); } return( CreateFromGdiplusBitmap( bmSrc ) );}

inlineHRESULTCImage::Save(IStream*pStream,REFGUIDguidFileType)constthrow(){if(!InitGDIPlus()){return(E_FAIL);}UINTnEncoders;UINTnBytes;Gdiplus::Statusstatus;status=Gdiplus::GetImageEncodersSize(&nEncoders,&nBytes);if(status!=Gdiplus::Ok){return(E_FAIL);}USES_ATL_SAFE_ALLOCA;Gdiplus::ImageCodecInfo*pEncoders=static_cast<Gdiplus::ImageCodecInfo*>(_ATL_SAFE_ALLOCA(nBytes,_ATL_SAFE_ALLOCA_DEF_THRESHOLD));if(pEncoders==NULL)returnE_OUTOFMEMORY;status=Gdiplus::GetImageEncoders(nEncoders,nBytes,pEncoders);if(status!=Gdiplus::Ok){return(E_FAIL);}CLSIDclsidEncoder=FindCodecForFileType(guidFileType,pEncoders,nEncoders);if(clsidEncoder==CLSID_NULL){return(E_FAIL);}if(m_bHasAlphaChannel){ATLASSUME(m_nBPP==32);Gdiplus::Bitmapbm(m_nWidth,m_nHeight,m_nPitch,PixelFormat32bppARGB,static_cast<BYTE*>(m_pBits));status=bm.Save(pStream,&clsidEncoder,NULL);if(status!=Gdiplus::Ok){return(E_FAIL);}}else{Gdiplus::Bitmapbm(m_hBitmap,NULL);status=bm.Save(pStream,&clsidEncoder,NULL);if(status!=Gdiplus::Ok){return(E_FAIL);}}return(S_OK);}inlineHRESULTCImage::Save(LPCTSTRpszFileName,REFGUIDguidFileType)constthrow(){if(!InitGDIPlus()){return(E_FAIL);}UINTnEncoders;UINTnBytes;Gdiplus::Statusstatus;status=Gdiplus::GetImageEncodersSize(&nEncoders,&nBytes);if(status!=Gdiplus::Ok){return(E_FAIL);}USES_CONVERSION_EX;Gdiplus::ImageCodecInfo*pEncoders=static_cast<Gdiplus::ImageCodecInfo*>(_ATL_SAFE_ALLOCA(nBytes,_ATL_SAFE_ALLOCA_DEF_THRESHOLD));if(pEncoders==NULL)returnE_OUTOFMEMORY;status=Gdiplus::GetImageEncoders(nEncoders,nBytes,pEncoders);if(status!=Gdiplus::Ok){return(E_FAIL);}CLSIDclsidEncoder=CLSID_NULL;if(guidFileType==GUID_NULL){//Determineclsidfromextension clsidEncoder=FindCodecForExtension(::PathFindExtension(pszFileName),pEncoders,nEncoders);}else{//Determineclsidfromfiletype clsidEncoder=FindCodecForFileType(guidFileType,pEncoders,nEncoders);}if(clsidEncoder==CLSID_NULL){return(E_FAIL);}LPCWSTRpwszFileName=T2CW_EX(pszFileName,_ATL_SAFE_ALLOCA_DEF_THRESHOLD);#ifndef_UNICODE if(pwszFileName==NULL)returnE_OUTOFMEMORY;#endif//_UNICODE if(m_bHasAlphaChannel){ATLASSUME(m_nBPP==32);Gdiplus::Bitmapbm(m_nWidth,m_nHeight,m_nPitch,PixelFormat32bppARGB,static_cast<BYTE*>(m_pBits));status=bm.Save(pwszFileName,&clsidEncoder,NULL);if(status!=Gdiplus::Ok){return(E_FAIL);}}else{Gdiplus::Bitmapbm(m_hBitmap,NULL);status=bm.Save(pwszFileName,&clsidEncoder,NULL);if(status!=Gdiplus::Ok){return(E_FAIL);}}return(S_OK);} inline HRESULT CImage::Save( IStream* pStream, REFGUID guidFileType ) const throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nEncoders; UINT nBytes; Gdiplus::Status status; status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } USES_ATL_SAFE_ALLOCA; Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pEncoders == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } CLSID clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders ); if( clsidEncoder == CLSID_NULL ) { return( E_FAIL ); } if( m_bHasAlphaChannel ) { ATLASSUME( m_nBPP == 32 ); Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) ); status = bm.Save( pStream, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } else { Gdiplus::Bitmap bm( m_hBitmap, NULL ); status = bm.Save( pStream, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } return( S_OK );}inline HRESULT CImage::Save( LPCTSTR pszFileName, REFGUID guidFileType ) const throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nEncoders; UINT nBytes; Gdiplus::Status status; status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } USES_CONVERSION_EX; Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pEncoders == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } CLSID clsidEncoder = CLSID_NULL; if( guidFileType == GUID_NULL ) { // Determine clsid from extension clsidEncoder = FindCodecForExtension( ::PathFindExtension( pszFileName ), pEncoders, nEncoders ); } else { // Determine clsid from file type clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders ); } if( clsidEncoder == CLSID_NULL ) { return( E_FAIL ); } LPCWSTR pwszFileName = T2CW_EX( pszFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD );#ifndef _UNICODE if( pwszFileName == NULL ) return E_OUTOFMEMORY;#endif // _UNICODE if( m_bHasAlphaChannel ) { ATLASSUME( m_nBPP == 32 ); Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) ); status = bm.Save( pwszFileName, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } else { Gdiplus::Bitmap bm( m_hBitmap, NULL ); status = bm.Save( pwszFileName, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } return( S_OK );}

有上面可知: CImage对象 在第一次Load() 或第一次Save() 时 启动GDI+

下面我们看看 CImage析构时,是否能将GDI+关闭掉:

inlineCImage::~CImage()throw(){Destroy();s_initGDIPlus.DecreaseCImageCount();} inline CImage::~CImage() throw(){ Destroy(); s_initGDIPlus.DecreaseCImageCount();}

inlinevoidCImage::CInitGDIPlus::DecreaseCImageCount()throw(){EnterCriticalSection(&m_sect);if(--m_nCImageObjects==0)ReleaseGDIPlus();LeaveCriticalSection(&m_sect);} inline void CImage::CInitGDIPlus::DecreaseCImageCount() throw(){ EnterCriticalSection(&m_sect); if( --m_nCImageObjects == 0 ) ReleaseGDIPlus(); LeaveCriticalSection(&m_sect);}

inlinevoidCImage::CInitGDIPlus::ReleaseGDIPlus()throw(){EnterCriticalSection(&m_sect);if(m_dwToken!=0){Gdiplus::GdiplusShutdown(m_dwToken);}m_dwToken=0;LeaveCriticalSection(&m_sect);} inline void CImage::CInitGDIPlus::ReleaseGDIPlus() throw(){ EnterCriticalSection(&m_sect); if( m_dwToken != 0 ) { Gdiplus::GdiplusShutdown( m_dwToken ); } m_dwToken = 0; LeaveCriticalSection(&m_sect);}

也就是说,一个CImage对象退出时,并不直接关闭GDI+ ,而是仅仅将GDI+使用计数减一, 当其为0时,再关闭GDI+

而这是通过类静态变量来实现计数的:

staticCInitGDIPluss_initGDIPlus; static CInitGDIPlus s_initGDIPlus;

由此,我们可作如下总结:

当定义多个CImge 变量时, 当某个变量加载图片或保存图片时,启动GDI+,之后, 当其他变量再加载图片或保存时,增加GDI+计数变量

当所有CImage变量都析构完毕时,才关闭GDI+,否则,只是减少GDI+计算变量值。

所以说,CImage类是基于GDI+的。

原文地址:/shuilan0066/article/details/7086371

我不喜欢做界面,所以就看过一次,因为我不会,所以有个印象。

CImage 是 GDI+ 里的东西

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
很久很久以前

很久很久以前

2023-02-25

在很久很久以前

在很久很久以前

2019-06-01

很久很久以前歌词

很久很久以前歌词

2019-02-05

很久很久以前英文

很久很久以前英文

2020-02-07