atlimage.h
上传用户:hfwmdy
上传日期:2016-01-14
资源大小:83k
文件大小:44k
源码类别:

GDI/图象编程

开发平台:

Visual C++

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. #ifndef __ATLIMAGE_H__
  11. #define __ATLIMAGE_H__
  12. #pragma once
  13. #include <atldef.h>
  14. #include <atlbase.h>
  15. #include <atlstr.h>
  16. #include <atlsimpcoll.h>
  17. #include <atltypes.h>
  18. #ifndef _ATL_NO_PRAGMA_WARNINGS
  19. #pragma warning (push)
  20. #pragma warning(disable : 4820) // padding added after member
  21. #endif //!_ATL_NO_PRAGMA_WARNINGS
  22. #pragma warning( push, 3 )
  23. #pragma push_macro("new")
  24. #undef new
  25. #include <gdiplus.h>
  26. #pragma pop_macro("new")
  27. #pragma warning( pop )
  28. #include <shlwapi.h>
  29. #ifndef _ATL_NO_DEFAULT_LIBS
  30. #pragma comment(lib, "gdi32.lib")
  31. #pragma comment(lib, "shlwapi.lib")
  32. #pragma comment(lib, "gdiplus.lib")
  33. #if WINVER >= 0x0500
  34. #pragma comment(lib, "msimg32.lib")
  35. #endif  // WINVER >= 0x0500
  36. #endif  // !_ATL_NO_DEFAULT_LIBS
  37. #pragma pack(push, _ATL_PACKING)
  38. namespace ATL
  39. {
  40. const int CIMAGE_DC_CACHE_SIZE = 4;
  41. class CImage;
  42. class CImageDC
  43. {
  44. public:
  45. CImageDC( const CImage& image ) throw( ... );
  46. ~CImageDC() throw();
  47. operator HDC() const throw();
  48. private:
  49. const CImage& m_image;
  50. HDC m_hDC;
  51. };
  52. class CImage
  53. {
  54. private:
  55. class CDCCache
  56. {
  57. public:
  58. CDCCache() throw();
  59. ~CDCCache() throw();
  60. HDC GetDC() throw();
  61. void ReleaseDC( HDC ) throw();
  62. private:
  63. HDC m_ahDCs[CIMAGE_DC_CACHE_SIZE];
  64. };
  65. class CInitGDIPlus
  66. {
  67. public:
  68. CInitGDIPlus() throw();
  69. ~CInitGDIPlus() throw();
  70. bool Init() throw();
  71. void ReleaseGDIPlus() throw();
  72. void IncreaseCImageCount() throw();
  73. void DecreaseCImageCount() throw();
  74. private:
  75. ULONG_PTR m_dwToken;
  76. CRITICAL_SECTION m_sect;
  77. LONG m_nCImageObjects;
  78. };
  79. public:
  80. static const DWORD createAlphaChannel = 0x01;
  81. static const DWORD excludeGIF = 0x01;
  82. static const DWORD excludeBMP = 0x02;
  83. static const DWORD excludeEMF = 0x04;
  84. static const DWORD excludeWMF = 0x08;
  85. static const DWORD excludeJPEG = 0x10;
  86. static const DWORD excludePNG = 0x20;
  87. static const DWORD excludeTIFF = 0x40;
  88. static const DWORD excludeIcon = 0x80;
  89. static const DWORD excludeOther = 0x80000000;
  90. static const DWORD excludeDefaultLoad = 0;
  91. static const DWORD excludeDefaultSave = excludeIcon|excludeEMF|excludeWMF;
  92. static const DWORD excludeValid = 0x800000ff;
  93. enum DIBOrientation
  94. {
  95. DIBOR_DEFAULT,
  96. DIBOR_TOPDOWN,
  97. DIBOR_BOTTOMUP
  98. };
  99. public:
  100. CImage() throw();
  101. virtual ~CImage() throw();
  102. operator HBITMAP() const throw();
  103. #if WINVER >= 0x0500
  104. BOOL AlphaBlend( HDC hDestDC, int xDest, int yDest, BYTE bSrcAlpha = 0xff, 
  105. BYTE bBlendOp = AC_SRC_OVER ) const throw();
  106. BOOL AlphaBlend( HDC hDestDC, const POINT& pointDest, BYTE bSrcAlpha = 0xff, 
  107. BYTE bBlendOp = AC_SRC_OVER ) const throw();
  108. BOOL AlphaBlend( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  109. int nDestHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, 
  110. BYTE bSrcAlpha = 0xff, BYTE bBlendOp = AC_SRC_OVER ) const throw();
  111. BOOL AlphaBlend( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc, 
  112. BYTE bSrcAlpha = 0xff, BYTE bBlendOp = AC_SRC_OVER ) const throw();
  113. #endif  // WINVER >= 0x0500
  114. void Attach( HBITMAP hBitmap, DIBOrientation eOrientation = DIBOR_DEFAULT ) throw();
  115. BOOL BitBlt( HDC hDestDC, int xDest, int yDest, DWORD dwROP = SRCCOPY ) const throw();
  116. BOOL BitBlt( HDC hDestDC, const POINT& pointDest, DWORD dwROP = SRCCOPY ) const throw();
  117. BOOL BitBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  118. int nDestHeight, int xSrc, int ySrc, DWORD dwROP = SRCCOPY ) const throw();
  119. BOOL BitBlt( HDC hDestDC, const RECT& rectDest, const POINT& pointSrc, 
  120. DWORD dwROP = SRCCOPY ) const throw();
  121. BOOL Create( int nWidth, int nHeight, int nBPP, DWORD dwFlags = 0 ) throw();
  122. BOOL CreateEx( int nWidth, int nHeight, int nBPP, DWORD eCompression, 
  123. const DWORD* pdwBitmasks = NULL, DWORD dwFlags = 0 ) throw();
  124. void Destroy() throw();
  125. HBITMAP Detach() throw();
  126. BOOL Draw( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  127. int nDestHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight ) const throw();
  128. BOOL Draw( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc ) const throw();
  129. BOOL Draw( HDC hDestDC, int xDest, int yDest ) const throw();
  130. BOOL Draw( HDC hDestDC, const POINT& pointDest ) const throw();
  131. BOOL Draw( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  132. int nDestHeight ) const throw();
  133. BOOL Draw( HDC hDestDC, const RECT& rectDest ) const throw();
  134. const void* GetBits() const throw();
  135. void* GetBits() throw();
  136. int GetBPP() const throw();
  137. void GetColorTable( UINT iFirstColor, UINT nColors, RGBQUAD* prgbColors ) const throw();
  138. HDC GetDC() const throw();
  139. static HRESULT GetExporterFilterString( CSimpleString& strExporters, 
  140. CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription = NULL, 
  141. DWORD dwExclude = excludeDefaultSave, TCHAR chSeparator = _T( '|' ) );
  142. static HRESULT GetImporterFilterString( CSimpleString& strImporters, 
  143. CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription = NULL, 
  144. DWORD dwExclude = excludeDefaultLoad, TCHAR chSeparator = _T( '|' ) );
  145. int GetHeight() const throw();
  146. int GetMaxColorTableEntries() const throw();
  147. int GetPitch() const throw();
  148. const void* GetPixelAddress( int x, int y ) const throw();
  149. void* GetPixelAddress( int x, int y ) throw();
  150. COLORREF GetPixel( int x, int y ) const throw();
  151. LONG GetTransparentColor() const throw();
  152. int GetWidth() const throw();
  153. bool IsDIBSection() const throw();
  154. bool IsIndexed() const throw();
  155. bool IsNull() const throw();
  156. HRESULT Load( LPCTSTR pszFileName ) throw();
  157. HRESULT Load( IStream* pStream ) throw();
  158. void LoadFromResource( HINSTANCE hInstance, LPCTSTR pszResourceName ) throw();
  159. void LoadFromResource( HINSTANCE hInstance, UINT nIDResource ) throw();
  160. BOOL MaskBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  161. int nDestHeight, int xSrc, int ySrc, HBITMAP hbmMask, int xMask, 
  162. int yMask, DWORD dwROP = SRCCOPY ) const throw();
  163. BOOL MaskBlt( HDC hDestDC, const RECT& rectDest, const POINT& pointSrc, 
  164. HBITMAP hbmMask, const POINT& pointMask, DWORD dwROP = SRCCOPY ) const throw();
  165. BOOL MaskBlt( HDC hDestDC, int xDest, int yDest, HBITMAP hbmMask, 
  166. DWORD dwROP = SRCCOPY ) const throw();
  167. BOOL MaskBlt( HDC hDestDC, const POINT& pointDest, HBITMAP hbmMask, 
  168. DWORD dwROP = SRCCOPY ) const throw();
  169. BOOL PlgBlt( HDC hDestDC, const POINT* pPoints, HBITMAP hbmMask = NULL ) const throw();
  170. BOOL PlgBlt( HDC hDestDC, const POINT* pPoints, int xSrc, int ySrc, 
  171. int nSrcWidth, int nSrcHeight, HBITMAP hbmMask = NULL, int xMask = 0, 
  172. int yMask = 0 ) const throw();
  173. BOOL PlgBlt( HDC hDestDC, const POINT* pPoints, const RECT& rectSrc, 
  174. HBITMAP hbmMask = NULL, const POINT& pointMask = CPoint( 0, 0 ) ) const throw();
  175. void ReleaseDC() const throw();
  176. HRESULT Save( IStream* pStream, REFGUID guidFileType ) const throw();
  177. HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType = GUID_NULL ) const throw();
  178. void SetColorTable( UINT iFirstColor, UINT nColors, 
  179. const RGBQUAD* prgbColors ) throw();
  180. void SetPixel( int x, int y, COLORREF color ) throw();
  181. void SetPixelIndexed( int x, int y, int iIndex ) throw();
  182. void SetPixelRGB( int x, int y, BYTE r, BYTE g, BYTE b ) throw();
  183. LONG SetTransparentColor( LONG iTransparentColor ) throw();
  184. BOOL StretchBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  185. int nDestHeight, DWORD dwROP = SRCCOPY ) const throw();
  186. BOOL StretchBlt( HDC hDestDC, const RECT& rectDest, DWORD dwROP = SRCCOPY ) const throw();
  187. BOOL StretchBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  188. int nDestHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight,
  189. DWORD dwROP = SRCCOPY ) const throw();
  190. BOOL StretchBlt( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc,
  191. DWORD dwROP = SRCCOPY ) const throw();
  192. #if WINVER >= 0x0500
  193. BOOL TransparentBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  194. int nDestHeight, UINT crTransparent = CLR_INVALID ) const throw();
  195. BOOL TransparentBlt( HDC hDestDC, const RECT& rectDest, 
  196. UINT crTransparent = CLR_INVALID ) const throw();
  197. BOOL TransparentBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth,
  198. int nDestHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight,
  199. UINT crTransparent = CLR_INVALID ) const throw();
  200. BOOL TransparentBlt( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc,
  201. UINT crTransparent = CLR_INVALID ) const throw();
  202. #endif  // WINVER >= 0x0500
  203. static BOOL IsTransparencySupported() throw();
  204. private:
  205. HBITMAP m_hBitmap;
  206. void* m_pBits;
  207. int m_nWidth;
  208. int m_nHeight;
  209. int m_nPitch;
  210. int m_nBPP;
  211. bool m_bIsDIBSection;
  212. bool m_bHasAlphaChannel;
  213. LONG m_iTransparentColor;
  214. static CInitGDIPlus s_initGDIPlus;
  215. public:
  216. inline static void ReleaseGDIPlus() { s_initGDIPlus.ReleaseGDIPlus(); }
  217. // Implementation
  218. private:
  219. static CLSID FindCodecForExtension( LPCTSTR pszExtension, const Gdiplus::ImageCodecInfo* pCodecs, UINT nCodecs );
  220. static CLSID FindCodecForFileType( REFGUID guidFileType, const Gdiplus::ImageCodecInfo* pCodecs, UINT nCodecs );
  221. static void BuildCodecFilterString( const Gdiplus::ImageCodecInfo* pCodecs, UINT nCodecs, 
  222. CSimpleString& strFilter, CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription, DWORD dwExclude, TCHAR chSeparator );
  223. static bool ShouldExcludeFormat( REFGUID guidFileType, DWORD dwExclude ) throw();
  224. void UpdateBitmapInfo( DIBOrientation eOrientation );
  225. HRESULT CreateFromGdiplusBitmap( Gdiplus::Bitmap& bmSrc ) throw();
  226. static bool InitGDIPlus() throw();
  227. static int ComputePitch( int nWidth, int nBPP )
  228. {
  229. return( (((nWidth*nBPP)+31)/32)*4 );
  230. }
  231. static void GenerateHalftonePalette( LPRGBQUAD prgbPalette );
  232. COLORREF GetTransparentRGB() const;
  233. private:
  234. mutable HDC m_hDC;
  235. mutable int m_nDCRefCount;
  236. mutable HBITMAP m_hOldBitmap;
  237. static CDCCache s_cache;
  238. };
  239. inline CImageDC::CImageDC( const CImage& image ) throw( ... ) :
  240. m_image( image ),
  241. m_hDC( image.GetDC() )
  242. {
  243. if( m_hDC == NULL )
  244. {
  245. AtlThrow( E_OUTOFMEMORY );
  246. }
  247. }
  248. inline CImageDC::~CImageDC() throw()
  249. {
  250. m_image.ReleaseDC();
  251. }
  252. inline CImageDC::operator HDC() const throw()
  253. {
  254. return( m_hDC );
  255. }
  256. inline CImage::CInitGDIPlus::CInitGDIPlus() throw() :
  257. m_dwToken( 0 ), m_nCImageObjects( 0 )
  258. {
  259. __try
  260. {
  261. InitializeCriticalSection(&m_sect);
  262. }
  263. __except( STATUS_NO_MEMORY == GetExceptionCode() )
  264. {
  265. AtlThrow( E_OUTOFMEMORY );
  266. }
  267. }
  268. inline CImage::CInitGDIPlus::~CInitGDIPlus() throw()
  269. {
  270. ReleaseGDIPlus();
  271. DeleteCriticalSection(&m_sect);
  272. }
  273. inline bool CImage::CInitGDIPlus::Init() throw()
  274. {
  275. EnterCriticalSection(&m_sect);
  276. bool fRet = true;
  277. if( m_dwToken == 0 )
  278. {
  279. Gdiplus::GdiplusStartupInput input;
  280. Gdiplus::GdiplusStartupOutput output;
  281. Gdiplus::Status status = Gdiplus::GdiplusStartup( &m_dwToken, &input, &output );
  282. if( status != Gdiplus::Ok )
  283. fRet = false;
  284. }
  285. LeaveCriticalSection(&m_sect);
  286. return fRet;
  287. }
  288. inline void CImage::CInitGDIPlus::ReleaseGDIPlus() throw()
  289. {
  290. EnterCriticalSection(&m_sect);
  291. if( m_dwToken != 0 )
  292. {
  293. Gdiplus::GdiplusShutdown( m_dwToken );
  294. }
  295. m_dwToken = 0;
  296. LeaveCriticalSection(&m_sect);
  297. }
  298. inline void CImage::CInitGDIPlus::IncreaseCImageCount() throw()
  299. {
  300. EnterCriticalSection(&m_sect);
  301. m_nCImageObjects++;
  302. LeaveCriticalSection(&m_sect);
  303. }
  304. inline void CImage::CInitGDIPlus::DecreaseCImageCount() throw()
  305. {
  306. EnterCriticalSection(&m_sect);
  307. if( --m_nCImageObjects == 0 )
  308. ReleaseGDIPlus();
  309. LeaveCriticalSection(&m_sect);
  310. }
  311. inline CImage::CDCCache::CDCCache() throw()
  312. {
  313. int iDC;
  314. for( iDC = 0; iDC < CIMAGE_DC_CACHE_SIZE; iDC++ )
  315. {
  316. m_ahDCs[iDC] = NULL;
  317. }
  318. }
  319. inline CImage::CDCCache::~CDCCache() throw()
  320. {
  321. int iDC;
  322. for( iDC = 0; iDC < CIMAGE_DC_CACHE_SIZE; iDC++ )
  323. {
  324. if( m_ahDCs[iDC] != NULL )
  325. {
  326. ::DeleteDC( m_ahDCs[iDC] );
  327. }
  328. }
  329. }
  330. inline HDC CImage::CDCCache::GetDC() throw()
  331. {
  332. HDC hDC;
  333. for( int iDC = 0; iDC < CIMAGE_DC_CACHE_SIZE; iDC++ )
  334. {
  335. hDC = static_cast< HDC >( InterlockedExchangePointer( reinterpret_cast< void** >(&m_ahDCs[iDC]), NULL ) );
  336. if( hDC != NULL )
  337. {
  338. return( hDC );
  339. }
  340. }
  341. hDC = ::CreateCompatibleDC( NULL );
  342. return( hDC );
  343. }
  344. inline void CImage::CDCCache::ReleaseDC( HDC hDC ) throw()
  345. {
  346. for( int iDC = 0; iDC < CIMAGE_DC_CACHE_SIZE; iDC++ )
  347. {
  348. HDC hOldDC;
  349. hOldDC = static_cast< HDC >( InterlockedExchangePointer( reinterpret_cast< void** >(&m_ahDCs[iDC]), hDC ) );
  350. if( hOldDC == NULL )
  351. {
  352. return;
  353. }
  354. else
  355. {
  356. hDC = hOldDC;
  357. }
  358. }
  359. if( hDC != NULL )
  360. {
  361. ::DeleteDC( hDC );
  362. }
  363. }
  364. inline CImage::CImage() throw() :
  365. m_hBitmap( NULL ),
  366. m_pBits( NULL ),
  367. m_hDC( NULL ),
  368. m_nDCRefCount( 0 ),
  369. m_hOldBitmap( NULL ),
  370. m_nWidth( 0 ),
  371. m_nHeight( 0 ),
  372. m_nPitch( 0 ),
  373. m_nBPP( 0 ),
  374. m_iTransparentColor( -1 ),
  375. m_bHasAlphaChannel( false ),
  376. m_bIsDIBSection( false )
  377. {
  378. s_initGDIPlus.IncreaseCImageCount();
  379. }
  380. inline CImage::~CImage() throw()
  381. {
  382. Destroy();
  383. s_initGDIPlus.DecreaseCImageCount();
  384. }
  385. inline CImage::operator HBITMAP() const throw()
  386. {
  387. return( m_hBitmap );
  388. }
  389. #if WINVER >= 0x0500
  390. inline BOOL CImage::AlphaBlend( HDC hDestDC, int xDest, int yDest, 
  391. BYTE bSrcAlpha, BYTE bBlendOp ) const throw()
  392. {
  393. return( AlphaBlend( hDestDC, xDest, yDest, m_nWidth, m_nHeight, 0, 0, 
  394. m_nWidth, m_nHeight, bSrcAlpha, bBlendOp ) );
  395. }
  396. inline BOOL CImage::AlphaBlend( HDC hDestDC, const POINT& pointDest, 
  397.    BYTE bSrcAlpha, BYTE bBlendOp ) const throw()
  398. {
  399. return( AlphaBlend( hDestDC, pointDest.x, pointDest.y, m_nWidth, m_nHeight, 
  400. 0, 0, m_nWidth, m_nHeight, bSrcAlpha, bBlendOp ) );
  401. }
  402. inline BOOL CImage::AlphaBlend( HDC hDestDC, int xDest, int yDest, 
  403. int nDestWidth, int nDestHeight, int xSrc, int ySrc, int nSrcWidth, 
  404. int nSrcHeight, BYTE bSrcAlpha, BYTE bBlendOp ) const throw()
  405. {
  406. BLENDFUNCTION blend;
  407. BOOL bResult;
  408. blend.SourceConstantAlpha = bSrcAlpha;
  409. blend.BlendOp = bBlendOp;
  410. blend.BlendFlags = 0;
  411. if( m_bHasAlphaChannel )
  412. {
  413. blend.AlphaFormat = AC_SRC_ALPHA;
  414. }
  415. else
  416. {
  417. blend.AlphaFormat = 0;
  418. }
  419. GetDC();
  420. bResult = ::AlphaBlend( hDestDC, xDest, yDest, nDestWidth, nDestHeight, m_hDC, 
  421. xSrc, ySrc, nSrcWidth, nSrcHeight, blend );
  422. ReleaseDC();
  423. return( bResult );
  424. }
  425. inline BOOL CImage::AlphaBlend( HDC hDestDC, const RECT& rectDest, 
  426. const RECT& rectSrc, BYTE bSrcAlpha, BYTE bBlendOp ) const throw()
  427. {
  428. return( AlphaBlend( hDestDC, rectDest.left, rectDest.top, rectDest.right-
  429. rectDest.left, rectDest.bottom-rectDest.top, rectSrc.left, rectSrc.top, 
  430. rectSrc.right-rectSrc.left, rectSrc.bottom-rectSrc.top, bSrcAlpha, 
  431. bBlendOp ) );
  432. }
  433. #endif  // WINVER >= 0x0500
  434. inline void CImage::Attach( HBITMAP hBitmap, DIBOrientation eOrientation ) throw()
  435. {
  436. ATLASSUME( m_hBitmap == NULL );
  437. ATLASSERT( hBitmap != NULL );
  438. m_hBitmap = hBitmap;
  439. UpdateBitmapInfo( eOrientation );
  440. }
  441. inline BOOL CImage::BitBlt( HDC hDestDC, int xDest, int yDest, DWORD dwROP ) const throw()
  442. {
  443. return( BitBlt( hDestDC, xDest, yDest, m_nWidth, m_nHeight, 0, 0, dwROP ) );
  444. }
  445. inline BOOL CImage::BitBlt( HDC hDestDC, const POINT& pointDest, DWORD dwROP ) const throw()
  446. {
  447. return( BitBlt( hDestDC, pointDest.x, pointDest.y, m_nWidth, m_nHeight,
  448. 0, 0, dwROP ) );
  449. }
  450. inline BOOL CImage::BitBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
  451. int nDestHeight, int xSrc, int ySrc, DWORD dwROP ) const throw()
  452. {
  453. BOOL bResult;
  454. ATLASSUME( m_hBitmap != NULL );
  455. ATLASSERT( hDestDC != NULL );
  456. GetDC();
  457. bResult = ::BitBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight, m_hDC, 
  458. xSrc, ySrc, dwROP );
  459. ReleaseDC();
  460. return( bResult );
  461. }
  462. inline BOOL CImage::BitBlt( HDC hDestDC, const RECT& rectDest, 
  463. const POINT& pointSrc, DWORD dwROP ) const throw()
  464. {
  465. return( BitBlt( hDestDC, rectDest.left, rectDest.top, rectDest.right-
  466. rectDest.left, rectDest.bottom-rectDest.top, pointSrc.x, pointSrc.y, 
  467. dwROP ) );
  468. }
  469. inline BOOL CImage::Create( int nWidth, int nHeight, int nBPP, DWORD dwFlags ) throw()
  470. {
  471. return( CreateEx( nWidth, nHeight, nBPP, BI_RGB, NULL, dwFlags ) );
  472. }
  473. inline BOOL CImage::CreateEx( int nWidth, int nHeight, int nBPP, DWORD eCompression, 
  474. const DWORD* pdwBitfields, DWORD dwFlags ) throw()
  475. {
  476. USES_ATL_SAFE_ALLOCA;
  477. LPBITMAPINFO pbmi;
  478. HBITMAP hBitmap;
  479. ATLASSERT( (eCompression == BI_RGB) || (eCompression == BI_BITFIELDS) );
  480. if( dwFlags&createAlphaChannel )
  481. {
  482. ATLASSERT( (nBPP == 32) && (eCompression == BI_RGB) );
  483. }
  484. pbmi = (LPBITMAPINFO)_ATL_SAFE_ALLOCA(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  485. if( pbmi == NULL )
  486. return FALSE;
  487. memset( &pbmi->bmiHeader, 0, sizeof( pbmi->bmiHeader ) );
  488. pbmi->bmiHeader.biSize = sizeof( pbmi->bmiHeader );
  489. pbmi->bmiHeader.biWidth = nWidth;
  490. pbmi->bmiHeader.biHeight = nHeight;
  491. pbmi->bmiHeader.biPlanes = 1;
  492. pbmi->bmiHeader.biBitCount = USHORT( nBPP );
  493. pbmi->bmiHeader.biCompression = eCompression;
  494. if( nBPP <= 8 )
  495. {
  496. ATLASSERT( eCompression == BI_RGB );
  497. #pragma warning(push)
  498. #pragma warning(disable:4068) //Disable unknown pragma warning that prefast pragma causes.
  499. #pragma prefast(push)
  500. #pragma prefast(disable:203, "no buffer overrun here, buffer was alocated properly")
  501. memset( pbmi->bmiColors, 0, 256*sizeof( RGBQUAD ) );
  502. #pragma prefast(pop)
  503. #pragma warning(pop)
  504. }
  505. else 
  506. {
  507. if( eCompression == BI_BITFIELDS )
  508. {
  509. ATLASSERT( pdwBitfields != NULL );
  510. Checked::memcpy_s(pbmi->bmiColors, 3*sizeof( DWORD ), pdwBitfields, 3*sizeof( DWORD ));
  511. }
  512. }
  513. hBitmap = ::CreateDIBSection( NULL, pbmi, DIB_RGB_COLORS, &m_pBits, NULL,
  514. 0 );
  515. if( hBitmap == NULL )
  516. {
  517. return( FALSE );
  518. }
  519. Attach( hBitmap, (nHeight < 0) ? DIBOR_TOPDOWN : DIBOR_BOTTOMUP );
  520. if( dwFlags&createAlphaChannel )
  521. {
  522. m_bHasAlphaChannel = true;
  523. }
  524. return( TRUE );
  525. }
  526. inline void CImage::Destroy() throw()
  527. {
  528. HBITMAP hBitmap;
  529. if( m_hBitmap != NULL )
  530. {
  531. hBitmap = Detach();
  532. ::DeleteObject( hBitmap );
  533. }
  534. }
  535. inline HBITMAP CImage::Detach() throw()
  536. {
  537. HBITMAP hBitmap;
  538. ATLASSUME( m_hBitmap != NULL );
  539. ATLASSUME( m_hDC == NULL );
  540. hBitmap = m_hBitmap;
  541. m_hBitmap = NULL;
  542. m_pBits = NULL;
  543. m_nWidth = 0;
  544. m_nHeight = 0;
  545. m_nBPP = 0;
  546. m_nPitch = 0;
  547. m_iTransparentColor = -1;
  548. m_bHasAlphaChannel = false;
  549. m_bIsDIBSection = false;
  550. return( hBitmap );
  551. }
  552. inline BOOL CImage::Draw( HDC hDestDC, const RECT& rectDest ) const throw()
  553. {
  554. return( Draw( hDestDC, rectDest.left, rectDest.top, rectDest.right-
  555. rectDest.left, rectDest.bottom-rectDest.top, 0, 0, m_nWidth, 
  556. m_nHeight ) );
  557. }
  558. inline BOOL CImage::Draw( HDC hDestDC, int xDest, int yDest, int nDestWidth, int nDestHeight ) const throw()
  559. {
  560. return( Draw( hDestDC, xDest, yDest, nDestWidth, nDestHeight, 0, 0, m_nWidth, m_nHeight ) );
  561. }
  562. inline BOOL CImage::Draw( HDC hDestDC, const POINT& pointDest ) const throw()
  563. {
  564. return( Draw( hDestDC, pointDest.x, pointDest.y, m_nWidth, m_nHeight, 0, 0, m_nWidth, m_nHeight ) );
  565. }
  566. inline BOOL CImage::Draw( HDC hDestDC, int xDest, int yDest ) const throw()
  567. {
  568. return( Draw( hDestDC, xDest, yDest, m_nWidth, m_nHeight, 0, 0, m_nWidth, m_nHeight ) );
  569. }
  570. inline BOOL CImage::Draw( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc ) const throw()
  571. {
  572. return( Draw( hDestDC, rectDest.left, rectDest.top, rectDest.right-
  573. rectDest.left, rectDest.bottom-rectDest.top, rectSrc.left, rectSrc.top, 
  574. rectSrc.right-rectSrc.left, rectSrc.bottom-rectSrc.top ) );
  575. }
  576. inline BOOL CImage::Draw( HDC hDestDC, int xDest, int yDest, int nDestWidth,
  577. int nDestHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight ) const throw()
  578. {
  579. BOOL bResult;
  580. ATLASSUME( m_hBitmap != NULL );
  581. ATLASSERT( hDestDC != NULL );
  582. ATLASSERT( nDestWidth > 0 );
  583. ATLASSERT( nDestHeight > 0 );
  584. ATLASSERT( nSrcWidth > 0 );
  585. ATLASSERT( nSrcHeight > 0 );
  586. GetDC();
  587. #if WINVER >= 0x0500
  588. if( (m_iTransparentColor != -1) && IsTransparencySupported() )
  589. {
  590. bResult = ::TransparentBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight,
  591. m_hDC, xSrc, ySrc, nSrcWidth, nSrcHeight, GetTransparentRGB() );
  592. }
  593. else if( m_bHasAlphaChannel && IsTransparencySupported() )
  594. {
  595. BLENDFUNCTION bf;
  596. bf.BlendOp = AC_SRC_OVER;
  597. bf.BlendFlags = 0;
  598. bf.SourceConstantAlpha = 0xff;
  599. bf.AlphaFormat = AC_SRC_ALPHA;
  600. bResult = ::AlphaBlend( hDestDC, xDest, yDest, nDestWidth, nDestHeight, 
  601. m_hDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf );
  602. }
  603. else
  604. #endif  // WINVER >= 0x0500
  605. {
  606. bResult = ::StretchBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight, 
  607. m_hDC, xSrc, ySrc, nSrcWidth, nSrcHeight, SRCCOPY );
  608. }
  609. ReleaseDC();
  610. return( bResult );
  611. }
  612. inline const void* CImage::GetBits() const throw()
  613. {
  614. ATLASSUME( m_hBitmap != NULL );
  615. ATLASSERT( IsDIBSection() );
  616. return( m_pBits );
  617. }
  618. inline void* CImage::GetBits() throw()
  619. {
  620. ATLASSUME( m_hBitmap != NULL );
  621. ATLASSERT( IsDIBSection() );
  622. return( m_pBits );
  623. }
  624. inline int CImage::GetBPP() const throw()
  625. {
  626. ATLASSUME( m_hBitmap != NULL );
  627. return( m_nBPP );
  628. }
  629. inline void CImage::GetColorTable( UINT iFirstColor, UINT nColors, 
  630. RGBQUAD* prgbColors ) const throw()
  631. {
  632. ATLASSUME( m_hBitmap != NULL );
  633. ATLASSUME( m_pBits != NULL );
  634. ATLASSERT( IsIndexed() );
  635. GetDC();
  636. ::GetDIBColorTable( m_hDC, iFirstColor, nColors, prgbColors );
  637. ReleaseDC();
  638. }
  639. inline HDC CImage::GetDC() const throw()
  640. {
  641. ATLASSUME( m_hBitmap != NULL );
  642. m_nDCRefCount++;
  643. if( m_hDC == NULL )
  644. {
  645. m_hDC = s_cache.GetDC();
  646. m_hOldBitmap = HBITMAP( ::SelectObject( m_hDC, m_hBitmap ) );
  647. }
  648. return( m_hDC );
  649. }
  650. inline bool CImage::ShouldExcludeFormat( REFGUID guidFileType, DWORD dwExclude ) throw()
  651. {
  652. static const GUID* apguidFormats[] =
  653. {
  654. &Gdiplus::ImageFormatGIF,
  655. &Gdiplus::ImageFormatBMP,
  656. &Gdiplus::ImageFormatEMF,
  657. &Gdiplus::ImageFormatWMF,
  658. &Gdiplus::ImageFormatJPEG,
  659. &Gdiplus::ImageFormatPNG,
  660. &Gdiplus::ImageFormatTIFF,
  661. &Gdiplus::ImageFormatIcon,
  662. NULL
  663. };
  664. ATLASSERT( (dwExclude|excludeValid) == excludeValid );
  665. for( int iFormat = 0; apguidFormats[iFormat] != NULL; iFormat++ )
  666. {
  667. if( guidFileType == *apguidFormats[iFormat] )
  668. {
  669. return( (dwExclude&(1<<iFormat)) != 0 );
  670. }
  671. }
  672. return( (dwExclude&excludeOther) != 0 );
  673. }
  674. inline void CImage::BuildCodecFilterString( const Gdiplus::ImageCodecInfo* pCodecs, UINT nCodecs,
  675. CSimpleString& strFilter, CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription, 
  676. DWORD dwExclude, TCHAR chSeparator )
  677. {
  678. if( pszAllFilesDescription != NULL )
  679. {
  680. aguidFileTypes.Add( GUID_NULL );
  681. }
  682. CString strAllExtensions;
  683. CString strTempFilter;
  684. for( UINT iCodec = 0; iCodec < nCodecs; iCodec++ )
  685. {
  686. const Gdiplus::ImageCodecInfo* pCodec = &pCodecs[iCodec];
  687. if( !ShouldExcludeFormat( pCodec->FormatID, dwExclude ) )
  688. {
  689. CW2CT pwszFilenameExtension( pCodec->FilenameExtension );
  690. strTempFilter += CW2CT( pCodec->FormatDescription );
  691. strTempFilter += _T( " (" );
  692. strTempFilter += pwszFilenameExtension;
  693. strTempFilter += _T( ")" );
  694. strTempFilter += chSeparator;
  695. strTempFilter += pwszFilenameExtension;
  696. strTempFilter += chSeparator;
  697. aguidFileTypes.Add( pCodec->FormatID );
  698. if( !strAllExtensions.IsEmpty() )
  699. {
  700. strAllExtensions += _T( ";" );
  701. }
  702. strAllExtensions += pwszFilenameExtension;
  703. }
  704. }
  705. if( pszAllFilesDescription != NULL )
  706. {
  707. strFilter += pszAllFilesDescription;
  708. strFilter += chSeparator;
  709. strFilter += strAllExtensions;
  710. strFilter += chSeparator;
  711. }
  712. strFilter += strTempFilter;
  713. strFilter += chSeparator;
  714. if( aguidFileTypes.GetSize() == 0 )
  715. {
  716. strFilter += chSeparator;
  717. }
  718. }
  719. inline HRESULT CImage::GetImporterFilterString( CSimpleString& strImporters, 
  720. CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription /* = NULL */,
  721. DWORD dwExclude /* = excludeDefaultLoad */, TCHAR chSeparator /* = '|' */ )
  722. {
  723. if( !InitGDIPlus() )
  724. {
  725. return( E_FAIL );
  726. }
  727. UINT nCodecs;
  728. UINT nSize;
  729. Gdiplus::Status status;
  730. Gdiplus::ImageCodecInfo* pCodecs;
  731. status = Gdiplus::GetImageDecodersSize( &nCodecs, &nSize );
  732. USES_ATL_SAFE_ALLOCA;
  733. pCodecs = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nSize, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) );
  734. if( pCodecs == NULL )
  735. return E_OUTOFMEMORY;
  736. status = Gdiplus::GetImageDecoders( nCodecs, nSize, pCodecs );
  737. BuildCodecFilterString( pCodecs, nCodecs, strImporters, aguidFileTypes, pszAllFilesDescription, dwExclude, chSeparator );
  738. return( S_OK );
  739. }
  740. inline HRESULT CImage::GetExporterFilterString( CSimpleString& strExporters, 
  741. CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription /* = NULL */,
  742. DWORD dwExclude /* = excludeDefaultSave */, TCHAR chSeparator /* = '|' */ )
  743. {
  744. if( !InitGDIPlus() )
  745. {
  746. return( E_FAIL );
  747. }
  748. UINT nCodecs;
  749. UINT nSize;
  750. Gdiplus::Status status;
  751. Gdiplus::ImageCodecInfo* pCodecs;
  752. status = Gdiplus::GetImageDecodersSize( &nCodecs, &nSize );
  753. USES_ATL_SAFE_ALLOCA;
  754. pCodecs = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nSize, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) );
  755. if( pCodecs == NULL )
  756. return E_OUTOFMEMORY;
  757. status = Gdiplus::GetImageDecoders( nCodecs, nSize, pCodecs );
  758. BuildCodecFilterString( pCodecs, nCodecs, strExporters, aguidFileTypes, pszAllFilesDescription, dwExclude, chSeparator );
  759. return( S_OK );
  760. }
  761. inline int CImage::GetHeight() const throw()
  762. {
  763. ATLASSUME( m_hBitmap != NULL );
  764. return( m_nHeight );
  765. }
  766. inline int CImage::GetMaxColorTableEntries() const throw()
  767. {
  768. ATLASSUME( m_hBitmap != NULL );
  769. ATLASSERT( IsDIBSection() );
  770. if( IsIndexed() )
  771. {
  772. return( 1<<m_nBPP );
  773. }
  774. else
  775. {
  776. return( 0 );
  777. }
  778. }
  779. inline int CImage::GetPitch() const throw()
  780. {
  781. ATLASSUME( m_hBitmap != NULL );
  782. ATLASSERT( IsDIBSection() );
  783. return( m_nPitch );
  784. }
  785. inline COLORREF CImage::GetPixel( int x, int y ) const throw()
  786. {
  787. ATLASSUME( m_hBitmap != NULL );
  788. ATLASSERT( (x >= 0) && (x < m_nWidth) );
  789. ATLASSERT( (y >= 0) && (y < m_nHeight) );
  790. GetDC();
  791. COLORREF clr = ::GetPixel( m_hDC, x, y );
  792. ReleaseDC();
  793. return( clr );
  794. }
  795. inline const void* CImage::GetPixelAddress( int x, int y ) const throw()
  796. {
  797. ATLASSUME( m_hBitmap != NULL );
  798. ATLASSERT( IsDIBSection() );
  799. ATLASSERT( (x >= 0) && (x < m_nWidth) );
  800. ATLASSERT( (y >= 0) && (y < m_nHeight) );
  801. return( LPBYTE( m_pBits )+(y*m_nPitch)+((x*m_nBPP)/8) );
  802. }
  803. inline void* CImage::GetPixelAddress( int x, int y ) throw()
  804. {
  805. ATLASSUME( m_hBitmap != NULL );
  806. ATLASSERT( IsDIBSection() );
  807. ATLASSERT( (x >= 0) && (x < m_nWidth) );
  808. ATLASSERT( (y >= 0) && (y < m_nHeight) );
  809. return( LPBYTE( m_pBits )+(y*m_nPitch)+((x*m_nBPP)/8) );
  810. }
  811. inline LONG CImage::GetTransparentColor() const throw()
  812. {
  813. ATLASSUME( m_hBitmap != NULL );
  814. ATLASSERT( (m_nBPP == 4) || (m_nBPP == 8) );
  815. return( m_iTransparentColor );
  816. }
  817. inline int CImage::GetWidth() const throw()
  818. {
  819. ATLASSUME( m_hBitmap != NULL );
  820. return( m_nWidth );
  821. }
  822. inline bool CImage::IsDIBSection() const throw()
  823. {
  824. return( m_bIsDIBSection );
  825. }
  826. inline bool CImage::IsIndexed() const throw()
  827. {
  828. ATLASSUME( m_hBitmap != NULL );
  829. ATLASSERT( IsDIBSection() );
  830. return( m_nBPP <= 8 );
  831. }
  832. inline bool CImage::IsNull() const throw()
  833. {
  834. return( m_hBitmap == NULL );
  835. }
  836. inline HRESULT CImage::Load( IStream* pStream ) throw()
  837. {
  838. if( !InitGDIPlus() )
  839. {
  840. return( E_FAIL );
  841. }
  842. Gdiplus::Bitmap bmSrc( pStream );
  843. if( bmSrc.GetLastStatus() != Gdiplus::Ok )
  844. {
  845. return( E_FAIL );
  846. }
  847. return( CreateFromGdiplusBitmap( bmSrc ) );
  848. }
  849. inline HRESULT CImage::Load( LPCTSTR pszFileName ) throw()
  850. {
  851. if( !InitGDIPlus() )
  852. {
  853. return( E_FAIL );
  854. }
  855. Gdiplus::Bitmap bmSrc( (CT2W)pszFileName );
  856. if( bmSrc.GetLastStatus() != Gdiplus::Ok )
  857. {
  858. return( E_FAIL );
  859. }
  860. return( CreateFromGdiplusBitmap( bmSrc ) );
  861. }
  862. inline HRESULT CImage::CreateFromGdiplusBitmap( Gdiplus::Bitmap& bmSrc ) throw()
  863. {
  864. Gdiplus::PixelFormat eSrcPixelFormat = bmSrc.GetPixelFormat();
  865. UINT nBPP = 32;
  866. DWORD dwFlags = 0;
  867. Gdiplus::PixelFormat eDestPixelFormat = PixelFormat32bppRGB;
  868. if( eSrcPixelFormat&PixelFormatGDI )
  869. {
  870. nBPP = Gdiplus::GetPixelFormatSize( eSrcPixelFormat );
  871. eDestPixelFormat = eSrcPixelFormat;
  872. }
  873. if( Gdiplus::IsAlphaPixelFormat( eSrcPixelFormat ) )
  874. {
  875. nBPP = 32;
  876. dwFlags |= createAlphaChannel;
  877. eDestPixelFormat = PixelFormat32bppARGB;
  878. }
  879. BOOL bSuccess = Create( bmSrc.GetWidth(), bmSrc.GetHeight(), nBPP, dwFlags );
  880. if( !bSuccess )
  881. {
  882. return( E_FAIL );
  883. }
  884. USES_ATL_SAFE_ALLOCA;
  885. Gdiplus::ColorPalette* pPalette = NULL;
  886. if( Gdiplus::IsIndexedPixelFormat( eSrcPixelFormat ) )
  887. {
  888. UINT nPaletteSize = bmSrc.GetPaletteSize();
  889. pPalette = static_cast< Gdiplus::ColorPalette* >( _ATL_SAFE_ALLOCA(nPaletteSize, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) );
  890. if( pPalette == NULL )
  891. return E_OUTOFMEMORY;
  892. bmSrc.GetPalette( pPalette, nPaletteSize );
  893. RGBQUAD argbPalette[256];
  894. ATLASSERT( (pPalette->Count > 0) && (pPalette->Count <= 256) );
  895. for( UINT iColor = 0; iColor < pPalette->Count; iColor++ )
  896. {
  897. Gdiplus::ARGB color = pPalette->Entries[iColor];
  898. argbPalette[iColor].rgbRed = (BYTE)( (color>>RED_SHIFT) & 0xff );
  899. argbPalette[iColor].rgbGreen = (BYTE)( (color>>GREEN_SHIFT) & 0xff );
  900. argbPalette[iColor].rgbBlue = (BYTE)( (color>>BLUE_SHIFT) & 0xff );
  901. argbPalette[iColor].rgbReserved = 0;
  902. }
  903. SetColorTable( 0, pPalette->Count, argbPalette );
  904. }
  905. if( eDestPixelFormat == eSrcPixelFormat )
  906. {
  907. // The pixel formats are identical, so just memcpy the rows.
  908. Gdiplus::BitmapData data;
  909. Gdiplus::Rect rect( 0, 0, GetWidth(), GetHeight() );
  910. if(bmSrc.LockBits( &rect, Gdiplus::ImageLockModeRead, eSrcPixelFormat, &data )!=Gdiplus::Ok)
  911. {
  912. return E_OUTOFMEMORY;
  913. }
  914. size_t nBytesPerRow = AtlAlignUp( nBPP*GetWidth(), 8 )/8;
  915. BYTE* pbDestRow = static_cast< BYTE* >( GetBits() );
  916. BYTE* pbSrcRow = static_cast< BYTE* >( data.Scan0 );
  917. for( int y = 0; y < GetHeight(); y++ )
  918. {
  919. Checked::memcpy_s(pbDestRow, nBytesPerRow, pbSrcRow, nBytesPerRow);
  920. pbDestRow += GetPitch();
  921. pbSrcRow += data.Stride;
  922. }
  923. bmSrc.UnlockBits( &data );
  924. }
  925. else
  926. {
  927. // Let GDI+ work its magic
  928. Gdiplus::Bitmap bmDest( GetWidth(), GetHeight(), GetPitch(), eDestPixelFormat, static_cast< BYTE* >( GetBits() ) );
  929. Gdiplus::Graphics gDest( &bmDest );
  930. gDest.DrawImage( &bmSrc, 0, 0 );
  931. }
  932. return( S_OK );
  933. }
  934. inline void CImage::LoadFromResource( HINSTANCE hInstance, LPCTSTR pszResourceName ) throw()
  935. {
  936. HBITMAP hBitmap;
  937. hBitmap = HBITMAP( ::LoadImage( hInstance, pszResourceName, IMAGE_BITMAP, 0, 
  938. 0, LR_CREATEDIBSECTION ) );
  939. Attach( hBitmap );
  940. }
  941. inline void CImage::LoadFromResource( HINSTANCE hInstance, UINT nIDResource ) throw()
  942. {
  943. LoadFromResource( hInstance, MAKEINTRESOURCE( nIDResource ) );
  944. }
  945. inline BOOL CImage::MaskBlt( HDC hDestDC, int xDest, int yDest, int nWidth, 
  946. int nHeight, int xSrc, int ySrc, HBITMAP hbmMask, int xMask, int yMask,
  947. DWORD dwROP ) const throw()
  948. {
  949. BOOL bResult;
  950. ATLASSUME( m_hBitmap != NULL );
  951. ATLASSERT( hDestDC != NULL );
  952. GetDC();
  953. bResult = ::MaskBlt( hDestDC, xDest, yDest, nWidth, nHeight, m_hDC, xSrc, 
  954. ySrc, hbmMask, xMask, yMask, dwROP );
  955. ReleaseDC();
  956. return( bResult );
  957. }
  958. inline BOOL CImage::MaskBlt( HDC hDestDC, const RECT& rectDest, 
  959. const POINT& pointSrc, HBITMAP hbmMask, const POINT& pointMask, 
  960. DWORD dwROP ) const throw()
  961. {
  962. return( MaskBlt( hDestDC, rectDest.left, rectDest.top, rectDest.right-
  963. rectDest.left, rectDest.bottom-rectDest.top, pointSrc.x, pointSrc.y, 
  964. hbmMask, pointMask.x, pointMask.y, dwROP ) );
  965. }
  966. inline BOOL CImage::MaskBlt( HDC hDestDC, int xDest, int yDest, HBITMAP hbmMask, 
  967. DWORD dwROP ) const throw()
  968. {
  969. return( MaskBlt( hDestDC, xDest, yDest, m_nWidth, m_nHeight, 0, 0, hbmMask, 
  970. 0, 0, dwROP ) );
  971. }
  972. inline BOOL CImage::MaskBlt( HDC hDestDC, const POINT& pointDest, HBITMAP hbmMask,
  973. DWORD dwROP ) const throw()
  974. {
  975. return( MaskBlt( hDestDC, pointDest.x, pointDest.y, m_nWidth, m_nHeight, 0, 
  976. 0, hbmMask, 0, 0, dwROP ) );
  977. }
  978. inline BOOL CImage::PlgBlt( HDC hDestDC, const POINT* pPoints, int xSrc, 
  979. int ySrc, int nSrcWidth, int nSrcHeight, HBITMAP hbmMask, int xMask, 
  980. int yMask ) const throw()
  981. {
  982. BOOL bResult;
  983. ATLASSUME( m_hBitmap != NULL );
  984. ATLASSERT( hDestDC != NULL );
  985. GetDC();
  986. bResult = ::PlgBlt( hDestDC, pPoints, m_hDC, xSrc, ySrc, nSrcWidth, 
  987. nSrcHeight, hbmMask, xMask, yMask );
  988. ReleaseDC();
  989. return( bResult );
  990. }
  991. inline BOOL CImage::PlgBlt( HDC hDestDC, const POINT* pPoints, 
  992. const RECT& rectSrc, HBITMAP hbmMask, const POINT& pointMask ) const throw()
  993. {
  994. return( PlgBlt( hDestDC, pPoints, rectSrc.left, rectSrc.top, rectSrc.right-
  995. rectSrc.left, rectSrc.bottom-rectSrc.top, hbmMask, pointMask.x, 
  996. pointMask.y ) );
  997. }
  998. inline BOOL CImage::PlgBlt( HDC hDestDC, const POINT* pPoints, 
  999. HBITMAP hbmMask ) const throw()
  1000. {
  1001. return( PlgBlt( hDestDC, pPoints, 0, 0, m_nWidth, m_nHeight, hbmMask, 0, 
  1002. 0 ) );
  1003. }
  1004. inline void CImage::ReleaseDC() const throw()
  1005. {
  1006. HBITMAP hBitmap;
  1007. ATLASSUME( m_hDC != NULL );
  1008. m_nDCRefCount--;
  1009. if( m_nDCRefCount == 0 )
  1010. {
  1011. hBitmap = HBITMAP( ::SelectObject( m_hDC, m_hOldBitmap ) );
  1012. ATLASSERT( hBitmap == m_hBitmap );
  1013. s_cache.ReleaseDC( m_hDC );
  1014. m_hDC = NULL;
  1015. }
  1016. }
  1017. inline CLSID CImage::FindCodecForExtension( LPCTSTR pszExtension, const Gdiplus::ImageCodecInfo* pCodecs, UINT nCodecs )
  1018. {
  1019. CT2CW pszExtensionW( pszExtension );
  1020. for( UINT iCodec = 0; iCodec < nCodecs; iCodec++ )
  1021. {
  1022. CStringW strExtensions( pCodecs[iCodec].FilenameExtension );
  1023. int iStart = 0;
  1024. do
  1025. {
  1026. CStringW strExtension = ::PathFindExtensionW( strExtensions.Tokenize( L";", iStart ) );
  1027. if( iStart != -1 )
  1028. {
  1029. if( strExtension.CompareNoCase( pszExtensionW ) == 0 )
  1030. {
  1031. return( pCodecs[iCodec].Clsid );
  1032. }
  1033. }
  1034. } while( iStart != -1 );
  1035. }
  1036. return( CLSID_NULL );
  1037. }
  1038. inline CLSID CImage::FindCodecForFileType( REFGUID guidFileType, const Gdiplus::ImageCodecInfo* pCodecs, UINT nCodecs )
  1039. {
  1040. for( UINT iCodec = 0; iCodec < nCodecs; iCodec++ )
  1041. {
  1042. if( pCodecs[iCodec].FormatID == guidFileType )
  1043. {
  1044. return( pCodecs[iCodec].Clsid );
  1045. }
  1046. }
  1047. return( CLSID_NULL );
  1048. }
  1049. inline HRESULT CImage::Save( IStream* pStream, REFGUID guidFileType ) const throw()
  1050. {
  1051. if( !InitGDIPlus() )
  1052. {
  1053. return( E_FAIL );
  1054. }
  1055. UINT nEncoders;
  1056. UINT nBytes;
  1057. Gdiplus::Status status;
  1058. status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes );
  1059. if( status != Gdiplus::Ok )
  1060. {
  1061. return( E_FAIL );
  1062. }
  1063. USES_ATL_SAFE_ALLOCA;
  1064. Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) );
  1065. if( pEncoders == NULL )
  1066. return E_OUTOFMEMORY;
  1067. status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders );
  1068. if( status != Gdiplus::Ok )
  1069. {
  1070. return( E_FAIL );
  1071. }
  1072. CLSID clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders );
  1073. if( clsidEncoder == CLSID_NULL )
  1074. {
  1075. return( E_FAIL );
  1076. }
  1077. if( m_bHasAlphaChannel )
  1078. {
  1079. ATLASSUME( m_nBPP == 32 );
  1080. Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) );
  1081. status = bm.Save( pStream, &clsidEncoder, NULL );
  1082. if( status != Gdiplus::Ok )
  1083. {
  1084. return( E_FAIL );
  1085. }
  1086. }
  1087. else
  1088. {
  1089. Gdiplus::Bitmap bm( m_hBitmap, NULL );
  1090. status = bm.Save( pStream, &clsidEncoder, NULL );
  1091. if( status != Gdiplus::Ok )
  1092. {
  1093. return( E_FAIL );
  1094. }
  1095. }
  1096. return( S_OK );
  1097. }
  1098. inline HRESULT CImage::Save( LPCTSTR pszFileName, REFGUID guidFileType ) const throw()
  1099. {
  1100. if( !InitGDIPlus() )
  1101. {
  1102. return( E_FAIL );
  1103. }
  1104. UINT nEncoders;
  1105. UINT nBytes;
  1106. Gdiplus::Status status;
  1107. status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes );
  1108. if( status != Gdiplus::Ok )
  1109. {
  1110. return( E_FAIL );
  1111. }
  1112. USES_CONVERSION_EX;
  1113. Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) );
  1114. if( pEncoders == NULL )
  1115. return E_OUTOFMEMORY;
  1116. status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders );
  1117. if( status != Gdiplus::Ok )
  1118. {
  1119. return( E_FAIL );
  1120. }
  1121. CLSID clsidEncoder = CLSID_NULL;
  1122. if( guidFileType == GUID_NULL )
  1123. {
  1124. // Determine clsid from extension
  1125. clsidEncoder = FindCodecForExtension( ::PathFindExtension( pszFileName ), pEncoders, nEncoders );
  1126. }
  1127. else
  1128. {
  1129. // Determine clsid from file type
  1130. clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders );
  1131. }
  1132. if( clsidEncoder == CLSID_NULL )
  1133. {
  1134. return( E_FAIL );
  1135. }
  1136. LPCWSTR pwszFileName = T2CW_EX( pszFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD );
  1137. #ifndef _UNICODE
  1138. if( pwszFileName == NULL )
  1139. return E_OUTOFMEMORY;
  1140. #endif // _UNICODE
  1141. if( m_bHasAlphaChannel )
  1142. {
  1143. ATLASSUME( m_nBPP == 32 );
  1144. Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) );
  1145. status = bm.Save( pwszFileName, &clsidEncoder, NULL );
  1146. if( status != Gdiplus::Ok )
  1147. {
  1148. return( E_FAIL );
  1149. }
  1150. }
  1151. else
  1152. {
  1153. Gdiplus::Bitmap bm( m_hBitmap, NULL );
  1154. status = bm.Save( pwszFileName, &clsidEncoder, NULL );
  1155. if( status != Gdiplus::Ok )
  1156. {
  1157. return( E_FAIL );
  1158. }
  1159. }
  1160. return( S_OK );
  1161. }
  1162. inline void CImage::SetColorTable( UINT iFirstColor, UINT nColors, 
  1163. const RGBQUAD* prgbColors ) throw()
  1164. {
  1165. ATLASSUME( m_hBitmap != NULL );
  1166. ATLASSERT( IsDIBSection() );
  1167. ATLASSERT( IsIndexed() );
  1168. GetDC();
  1169. ::SetDIBColorTable( m_hDC, iFirstColor, nColors, prgbColors );
  1170. ReleaseDC();
  1171. }
  1172. inline void CImage::SetPixel( int x, int y, COLORREF color ) throw()
  1173. {
  1174. ATLASSUME( m_hBitmap != NULL );
  1175. ATLASSERT( (x >= 0) && (x < m_nWidth) );
  1176. ATLASSERT( (y >= 0) && (y < m_nHeight) );
  1177. GetDC();
  1178. ::SetPixel( m_hDC, x, y, color );
  1179. ReleaseDC();
  1180. }
  1181. inline void CImage::SetPixelIndexed( int x, int y, int iIndex ) throw()
  1182. {
  1183. SetPixel( x, y, PALETTEINDEX( iIndex ) );
  1184. }
  1185. inline void CImage::SetPixelRGB( int x, int y, BYTE r, BYTE g, BYTE b ) throw()
  1186. {
  1187. SetPixel( x, y, RGB( r, g, b ) );
  1188. }
  1189. inline LONG CImage::SetTransparentColor( LONG iTransparentColor ) throw()
  1190. {
  1191. LONG iOldTransparentColor;
  1192. ATLASSUME( m_hBitmap != NULL );
  1193. ATLASSERT( (m_nBPP == 4) || (m_nBPP == 8) );
  1194. ATLASSERT( iTransparentColor < GetMaxColorTableEntries() );
  1195. ATLASSERT( iTransparentColor >= -1 );
  1196. iOldTransparentColor = m_iTransparentColor;
  1197. m_iTransparentColor = iTransparentColor;
  1198. return( iOldTransparentColor );
  1199. }
  1200. inline BOOL CImage::StretchBlt( HDC hDestDC, int xDest, int yDest, 
  1201. int nDestWidth, int nDestHeight, DWORD dwROP ) const throw()
  1202. {
  1203. return( StretchBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight, 0, 0, 
  1204. m_nWidth, m_nHeight, dwROP ) );
  1205. }
  1206. inline BOOL CImage::StretchBlt( HDC hDestDC, const RECT& rectDest, 
  1207. DWORD dwROP ) const throw()
  1208. {
  1209. return( StretchBlt( hDestDC, rectDest.left, rectDest.top, rectDest.right-
  1210. rectDest.left, rectDest.bottom-rectDest.top, 0, 0, m_nWidth, m_nHeight, 
  1211. dwROP ) );
  1212. }
  1213. inline BOOL CImage::StretchBlt( HDC hDestDC, int xDest, int yDest, 
  1214. int nDestWidth, int nDestHeight, int xSrc, int ySrc, int nSrcWidth, 
  1215. int nSrcHeight, DWORD dwROP ) const throw()
  1216. {
  1217. BOOL bResult;
  1218. ATLASSUME( m_hBitmap != NULL );
  1219. ATLASSERT( hDestDC != NULL );
  1220. GetDC();
  1221. bResult = ::StretchBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight, m_hDC,
  1222. xSrc, ySrc, nSrcWidth, nSrcHeight, dwROP );
  1223. ReleaseDC();
  1224. return( bResult );
  1225. }
  1226. inline BOOL CImage::StretchBlt( HDC hDestDC, const RECT& rectDest, 
  1227. const RECT& rectSrc, DWORD dwROP ) const throw()
  1228. {
  1229. return( StretchBlt( hDestDC, rectDest.left, rectDest.top, rectDest.right-
  1230. rectDest.left, rectDest.bottom-rectDest.top, rectSrc.left, rectSrc.top, 
  1231. rectSrc.right-rectSrc.left, rectSrc.bottom-rectSrc.top, dwROP ) );
  1232. }
  1233. #if WINVER >= 0x0500
  1234. inline BOOL CImage::TransparentBlt( HDC hDestDC, int xDest, int yDest, 
  1235. int nDestWidth, int nDestHeight, UINT crTransparent ) const throw()
  1236. {
  1237. return( TransparentBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight, 0, 
  1238. 0, m_nWidth, m_nHeight, crTransparent ) );
  1239. }
  1240. inline BOOL CImage::TransparentBlt( HDC hDestDC, const RECT& rectDest, 
  1241. UINT crTransparent ) const throw()
  1242. {
  1243. return( TransparentBlt( hDestDC, rectDest.left, rectDest.top, 
  1244. rectDest.right-rectDest.left, rectDest.bottom-rectDest.top, 
  1245. crTransparent ) );
  1246. }
  1247. inline BOOL CImage::TransparentBlt( HDC hDestDC, int xDest, int yDest, 
  1248. int nDestWidth, int nDestHeight, int xSrc, int ySrc, int nSrcWidth, 
  1249. int nSrcHeight, UINT crTransparent ) const throw()
  1250. {
  1251. BOOL bResult;
  1252. ATLASSUME( m_hBitmap != NULL );
  1253. ATLASSERT( hDestDC != NULL );
  1254. GetDC();
  1255. if( crTransparent == CLR_INVALID )
  1256. {
  1257. crTransparent = GetTransparentRGB();
  1258. }
  1259. bResult = ::TransparentBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight,
  1260. m_hDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent );
  1261. ReleaseDC();
  1262. return( bResult );
  1263. }
  1264. inline BOOL CImage::TransparentBlt( HDC hDestDC, const RECT& rectDest, 
  1265. const RECT& rectSrc, UINT crTransparent ) const throw()
  1266. {
  1267. return( TransparentBlt( hDestDC, rectDest.left, rectDest.top, 
  1268. rectDest.right-rectDest.left, rectDest.bottom-rectDest.top, rectSrc.left, 
  1269. rectSrc.top, rectSrc.right-rectSrc.left, rectSrc.bottom-rectSrc.top, 
  1270. crTransparent ) );
  1271. }
  1272. #endif  // WINVER >= 0x0500
  1273. inline BOOL CImage::IsTransparencySupported() throw()
  1274. {
  1275. #if WINVER >= 0x0500
  1276. return( _AtlBaseModule.m_bNT5orWin98 );
  1277. #else  // WINVER < 0x0500
  1278. return( FALSE );
  1279. #endif  // WINVER >= 0x0500
  1280. }
  1281. inline void CImage::UpdateBitmapInfo( DIBOrientation eOrientation )
  1282. {
  1283. DIBSECTION dibsection;
  1284. int nBytes;
  1285. nBytes = ::GetObject( m_hBitmap, sizeof( DIBSECTION ), &dibsection );
  1286. if( nBytes == sizeof( DIBSECTION ) )
  1287. {
  1288. m_bIsDIBSection = true;
  1289. m_nWidth = dibsection.dsBmih.biWidth;
  1290. m_nHeight = abs( dibsection.dsBmih.biHeight );
  1291. m_nBPP = dibsection.dsBmih.biBitCount;
  1292. m_nPitch = ComputePitch( m_nWidth, m_nBPP );
  1293. m_pBits = dibsection.dsBm.bmBits;
  1294. if( eOrientation == DIBOR_DEFAULT )
  1295. {
  1296. eOrientation = (dibsection.dsBmih.biHeight > 0) ? DIBOR_BOTTOMUP : DIBOR_TOPDOWN;
  1297. }
  1298. if( eOrientation == DIBOR_BOTTOMUP )
  1299. {
  1300. m_pBits = LPBYTE( m_pBits )+((m_nHeight-1)*m_nPitch);
  1301. m_nPitch = -m_nPitch;
  1302. }
  1303. }
  1304. else
  1305. {
  1306. // Non-DIBSection
  1307. ATLASSERT( nBytes == sizeof( BITMAP ) );
  1308. m_bIsDIBSection = false;
  1309. m_nWidth = dibsection.dsBm.bmWidth;
  1310. m_nHeight = dibsection.dsBm.bmHeight;
  1311. m_nBPP = dibsection.dsBm.bmBitsPixel;
  1312. m_nPitch = 0;
  1313. m_pBits = 0;
  1314. }
  1315. m_iTransparentColor = -1;
  1316. m_bHasAlphaChannel = false;
  1317. }
  1318. inline void CImage::GenerateHalftonePalette( LPRGBQUAD prgbPalette )
  1319. {
  1320. int r;
  1321. int g;
  1322. int b;
  1323. int gray;
  1324. LPRGBQUAD prgbEntry;
  1325. prgbEntry = prgbPalette;
  1326. for( r = 0; r < 6; r++ )
  1327. {
  1328. for( g = 0; g < 6; g++ )
  1329. {
  1330. for( b = 0; b < 6; b++ )
  1331. {
  1332. prgbEntry->rgbBlue = BYTE( b*255/5 );
  1333. prgbEntry->rgbGreen = BYTE( g*255/5 );
  1334. prgbEntry->rgbRed = BYTE( r*255/5 );
  1335. prgbEntry->rgbReserved = 0;
  1336. prgbEntry++;
  1337. }
  1338. }
  1339. }
  1340. for( gray = 0; gray < 20; gray++ )
  1341. {
  1342. prgbEntry->rgbBlue = BYTE( gray*255/20 );
  1343. prgbEntry->rgbGreen = BYTE( gray*255/20 );
  1344. prgbEntry->rgbRed = BYTE( gray*255/20 );
  1345. prgbEntry->rgbReserved = 0;
  1346. prgbEntry++;
  1347. }
  1348. }
  1349. inline COLORREF CImage::GetTransparentRGB() const
  1350. {
  1351. RGBQUAD rgb;
  1352. ATLASSUME( m_hDC != NULL );  // Must have a DC
  1353. ATLASSUME( m_iTransparentColor != -1 );
  1354. ::GetDIBColorTable( m_hDC, m_iTransparentColor, 1, &rgb );
  1355. return( RGB( rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue ) );
  1356. }
  1357. inline bool CImage::InitGDIPlus() throw()
  1358. {
  1359. bool bSuccess = s_initGDIPlus.Init();
  1360. return( bSuccess );
  1361. }
  1362. };  // namespace ATL
  1363. #pragma pack(pop)
  1364. #ifndef _ATL_NO_PRAGMA_WARNINGS
  1365. #pragma warning (pop)
  1366. #endif
  1367. #endif  // __ATLIMAGE_H__