Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1559 lines
39 KiB

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