日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2025/3/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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__ ??
  • ??
  • #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)??
  • #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的定義:

  • 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;??
  • ????};??
  • 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; };


    ?

  • static?CInitGDIPlus?s_initGDIPlus;??
  • static CInitGDIPlus s_initGDIPlus;

    ?

  • static?CDCCache?s_cache;??
  • static CDCCache s_cache;



    它定義了兩個類成員變量: 其中CInitGDIPlus 是負責GDI+的啟動和釋放

    ?

    我們再看一下,這個成員類的Init()方法:

    ?

  • 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;??
  • }??
  • 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+

    ?

    再看下一個函數:

  • inline?void?CImage::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 構造函數

  • 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();??
  • }??
  • 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();}


    ?

  • inline?void?CImage::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+

    ?

    我們繼續查找:

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


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

    因此我們查找InitGDIPlus() 的所有引用 ,發現以下函數:

    ?

  • 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?);??
  • }??
  • 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 );}


    ?

  • 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?)?);??
  • }??
  • 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 ) );}


    ?

  • 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?);??
  • }??
  • 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+關閉掉:

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


    ?

  • inline?void?CImage::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);}


    ?

  • inline?void?CImage::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+

    而這是通過類靜態變量來實現計數的:

  • static?CInitGDIPlus?s_initGDIPlus;??
  • static CInitGDIPlus s_initGDIPlus;


    ?

    由此,我們可作如下總結:

    ?

    ????? 當定義多個CImge 變量時, 當某個變量加載圖片或保存圖片時,啟動GDI+,之后, 當其他變量再加載圖片或保存時,增加GDI+計數變量

    ????? 當所有CImage變量都析構完畢時,才關閉GDI+,否則,只是減少GDI+計算變量值。

    ??? ? 所以說,CImage類是基于GDI+的。


    原文地址:http://blog.csdn.net/shuilan0066/article/details/7086371?

    我不喜歡做界面,所以就看過一次,因為我不會,所以有個印象。

    CImage 是 GDI+ 里的東西?

    ?

    轉載于:https://www.cnblogs.com/suanguade/p/4038055.html

    總結

    以上是生活随笔為你收集整理的CImage 是基于GDI+的,很老的一篇文章,我很久很久以前看到过的的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。