ExtSkinBitmap.cpp
上传用户:sesekoo
上传日期:2020-07-18
资源大小:21543k
文件大小:19k
源码类别:

界面编程

开发平台:

Visual C++

  1. // This is part of the Professional User Interface Suite library.
  2. // Copyright (C) 2001-2009 FOSS Software, Inc.
  3. // All rights reserved.
  4. //
  5. // http://www.prof-uis.com
  6. // mailto:support@prof-uis.com
  7. //
  8. // This source code can be used, modified and redistributed
  9. // under the terms of the license agreement that is included
  10. // in the Professional User Interface Suite package.
  11. //
  12. // Warranties and Disclaimers:
  13. // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND
  14. // INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  16. // IN NO EVENT WILL FOSS SOFTWARE INC. BE LIABLE FOR ANY DIRECT,
  17. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES,
  18. // INCLUDING DAMAGES FOR LOSS OF PROFITS, LOSS OR INACCURACY OF DATA,
  19. // INCURRED BY ANY PERSON FROM SUCH PERSON'S USAGE OF THIS SOFTWARE
  20. // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  21. #include "StdAfx.h"
  22. #if (!defined __PROF_SKIN_BITMAP_H)
  23. #include <../ProfSkin/ExtSkinBitmap.h>
  24. #endif
  25. #include <PNG.h>
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. CExtSkinBitmap::CExtSkinBitmap()
  32. {
  33. }
  34. CExtSkinBitmap::CExtSkinBitmap(
  35. const CExtBitmap & other
  36. )
  37. : CExtBitmapCache( other )
  38. {
  39. }
  40. CExtSkinBitmap::~CExtSkinBitmap()
  41. {
  42. Empty();
  43. }
  44. bool CExtSkinBitmap::AssignFromOther(
  45. const CExtBitmap & other,
  46. bool bEnableThrowException // = false
  47. )
  48. {
  49. bool bRetVal =
  50. CExtBitmapCache::AssignFromOther(
  51. other,
  52. bEnableThrowException
  53. );
  54. return bRetVal;
  55. }
  56. void CExtSkinBitmap::Empty()
  57. {
  58. CExtBitmapCache::Empty();
  59. }
  60. bool CExtSkinBitmap::IsEmpty() const
  61. {
  62. bool bRetVal = CExtBitmapCache::IsEmpty();
  63. return bRetVal;
  64. }
  65. bool CExtSkinBitmap::LoadImage_File(
  66. __EXT_MFC_SAFE_LPCTSTR strFilePath,
  67. bool bMake32, //= false
  68. bool bEnableThrowException //= false
  69. )
  70. {
  71. if( !strFilePath || _tcslen( strFilePath ) == 0 )
  72. return false;
  73. TCHAR sExt[_MAX_EXT] = { 0 };
  74. __EXT_MFC_SPLITPATH( strFilePath, NULL, 0, NULL, 0, NULL, 0, sExt, _MAX_EXT );
  75. if( _tcsicmp( sExt, _T( ".png" ) ) == 0 )
  76. {
  77. if( ! LoadPNG_File( strFilePath, bMake32, bEnableThrowException ) )
  78. return false;
  79. return true;
  80. }
  81. else if( _tcsicmp( sExt, _T( ".bmp" ) ) == 0 )
  82. return LoadBMP_File( strFilePath, bMake32, bEnableThrowException );
  83. if( LoadPNG_File( strFilePath, bMake32, false ) )
  84. return true;
  85. if( LoadBMP_File( strFilePath, bMake32, false ) )
  86. return true;
  87. if( bEnableThrowException )
  88. AfxThrowUserException();
  89. return false;
  90. }
  91. bool CExtSkinBitmap::LoadPNG_Resource(
  92. HINSTANCE hInst,
  93. HRSRC hRsrc,
  94. bool bMake32, // = true
  95. bool bEnableThrowException // = false
  96. )
  97. {
  98. HGLOBAL hGlobal = ::LoadResource( hInst, hRsrc );
  99. if( hGlobal == NULL )
  100. {
  101. if( bEnableThrowException )
  102. ::AfxThrowUserException();
  103. return false;
  104. } // if( hGlobal == NULL )
  105. LPBYTE pData = (LPBYTE)::LockResource( hGlobal );
  106. DWORD dwResourceSize = ::SizeofResource( hInst, hRsrc );
  107. ASSERT( dwResourceSize > 0 );
  108. if( pData == NULL )
  109. {
  110. ::FreeResource( hGlobal );
  111. if( bEnableThrowException )
  112. ::AfxThrowUserException();
  113. return false;
  114. } // if( pData == NULL )
  115. try
  116. {
  117. CMemFile _file;
  118. _file.Attach( pData, dwResourceSize );
  119. _file.Seek( 0, CFile::begin );
  120. CArchive ar( &_file, CArchive::load );
  121. bool bRetVal =
  122. LoadPNG(
  123. ar,
  124. bMake32,
  125. bEnableThrowException
  126. );
  127. ::UnlockResource( hGlobal );
  128. ::FreeResource( hGlobal );
  129. return bRetVal;
  130. } // try
  131. catch( CException * pException )
  132. {
  133. ::UnlockResource( hGlobal );
  134. ::FreeResource( hGlobal );
  135. if( bEnableThrowException )
  136. throw;
  137. pException->Delete();
  138. } // catch( CException * pException )
  139. catch( ... )
  140. {
  141. ::UnlockResource( hGlobal );
  142. ::FreeResource( hGlobal );
  143. if( bEnableThrowException )
  144. throw;
  145. } // catch( ... )
  146. return false;
  147. }
  148. bool CExtSkinBitmap::LoadPNG_File(
  149. __EXT_MFC_SAFE_LPCTSTR strFilePath,
  150. bool bMake32, // = true
  151. bool bEnableThrowException // = false
  152. )
  153. {
  154. try
  155. {
  156. CFile _file(
  157. strFilePath,
  158. CFile::modeRead
  159. | CFile::typeBinary
  160. );
  161. return
  162. LoadPNG_File(
  163. _file,
  164. bMake32,
  165. bEnableThrowException
  166. );
  167. } // try
  168. catch( ... )
  169. {
  170. if( bEnableThrowException )
  171. throw;
  172. } // catch( ... )
  173. return false;
  174. }
  175. bool CExtSkinBitmap::LoadPNG_File(
  176. CFile & _file,
  177. bool bMake32, // = true
  178. bool bEnableThrowException // = false
  179. )
  180. {
  181. CArchive ar(
  182. &_file,
  183. CArchive::load
  184. );
  185. return
  186. LoadPNG(
  187. ar,
  188. bMake32,
  189. bEnableThrowException
  190. );
  191. }
  192. bool CExtSkinBitmap::LoadPNG(
  193. CArchive & ar,
  194. bool bMake32, // = true
  195. bool bEnableThrowException // = false
  196. )
  197. {
  198. ASSERT( ar.IsLoading() );
  199. Empty();
  200. m_pImageBuffer =
  201. stat_PngLoad(
  202. ar,
  203. bEnableThrowException
  204. );
  205. if( m_pImageBuffer == NULL )
  206. return false;
  207. OnLoad();
  208. if( bMake32 )
  209. return Make32( bEnableThrowException );
  210. return true;
  211. }
  212. bool CExtSkinBitmap::SavePNG_File(
  213. __EXT_MFC_SAFE_LPCTSTR strFilePath,
  214. bool bMake32, // = true
  215. bool bEnableThrowException // = false
  216. )
  217. {
  218. try
  219. {
  220. CFile _file(
  221. strFilePath,
  222. CFile::modeCreate
  223. | CFile::modeWrite
  224. | CFile::typeBinary
  225. );
  226. return
  227. SavePNG_File(
  228. _file,
  229. bMake32,
  230. bEnableThrowException
  231. );
  232. } // try
  233. catch( ... )
  234. {
  235. if( bEnableThrowException )
  236. throw;
  237. } // catch( ... )
  238. return false;
  239. }
  240. bool CExtSkinBitmap::SavePNG_File(
  241. CFile & _file,
  242. bool bMake32, // = true
  243. bool bEnableThrowException // = false
  244. )
  245. {
  246. CArchive ar(
  247. &_file,
  248. CArchive::store
  249. );
  250. return
  251. SavePNG(
  252. ar,
  253. bMake32,
  254. bEnableThrowException
  255. );
  256. }
  257. bool CExtSkinBitmap::SavePNG(
  258. CArchive & ar,
  259. bool bMake32, // = true
  260. bool bEnableThrowException // = false
  261. )
  262. {
  263. ASSERT( ar.IsStoring() );
  264. if( m_pImageBuffer == NULL )
  265. {
  266. ASSERT( FALSE );
  267. if( bEnableThrowException )
  268. ::AfxThrowUserException();
  269. return false;
  270. } // if( m_pImageBuffer == NULL )
  271. if( bMake32 )
  272. {
  273. if( ! Make32( bEnableThrowException ) )
  274. return false;
  275. } // if( bMake32 )
  276. return
  277. stat_PngSave(
  278. m_pImageBuffer,
  279. ar,
  280. bEnableThrowException
  281. );
  282. }
  283. void CExtSkinBitmap::stat_PngCallbackRead(
  284. LPVOID pCallbackData,
  285. LPBYTE pBuffer,
  286. size_t nSize
  287. )
  288. {
  289. ASSERT( pCallbackData != NULL );
  290. CArchive * pAr = (CArchive *)
  291. ::png_get_io_ptr(
  292. (png_structp) pCallbackData
  293. );
  294. ASSERT( pAr != NULL );
  295. pAr->Read( pBuffer, UINT(nSize) );
  296. }
  297. void CExtSkinBitmap::stat_PngCallbackWrite(
  298. LPVOID pCallbackData,
  299. LPBYTE pBuffer,
  300. size_t nSize
  301. )
  302. {
  303. ASSERT( pCallbackData != NULL );
  304. CArchive * pAr = (CArchive *)
  305. ::png_get_io_ptr(
  306. (png_structp) pCallbackData
  307. );
  308. ASSERT( pAr != NULL );
  309. pAr->Write( pBuffer, UINT(nSize) );
  310. }
  311. void CExtSkinBitmap::stat_PngCallbackFlush(
  312. LPVOID pCallbackData
  313. )
  314. {
  315. ASSERT( pCallbackData != NULL );
  316. CArchive * pAr = (CArchive *)
  317. ::png_get_io_ptr(
  318. (png_structp) pCallbackData
  319. );
  320. ASSERT( pAr != NULL );
  321. pAr->Flush();
  322. }
  323. void CExtSkinBitmap::stat_PngCallbackError(
  324. LPVOID pCallbackData,
  325. const char * strErrorDescription
  326. )
  327. {
  328. pCallbackData;
  329. strErrorDescription;
  330. ::AfxThrowUserException();
  331. }
  332. void CExtSkinBitmap::stat_PngCallbackWarning(
  333. LPVOID pCallbackData,
  334. const char * strWarningDescription
  335. )
  336. {
  337. pCallbackData;
  338. strWarningDescription;
  339. }
  340. bool CExtSkinBitmap::stat_PngCheckSwap32(
  341. LPBYTE pImageBuffer
  342. )
  343. {
  344. ASSERT( pImageBuffer != NULL );
  345. LPBITMAPINFOHEADER pBIH = stat_RcInfoHeader( pImageBuffer );
  346. if( pBIH->biBitCount == 32 || pBIH->biBitCount == 24 )
  347. {
  348. DWORD r = stat_MaskRed( pImageBuffer );
  349. DWORD g = stat_MaskGreen( pImageBuffer );
  350. DWORD b = stat_MaskBlue( pImageBuffer );
  351. if( r == 0x00ff0000
  352. && g == 0x0000ff00
  353. && b == 0x000000ff
  354. )
  355. {
  356. ULONG nScanLineSize = stat_RcScanLineSize( pBIH->biWidth, pBIH->biBitCount );
  357. INT x, y;
  358. for( y = 0; y < pBIH->biHeight; y++ )
  359. {
  360. LPBYTE pScanLine =
  361. stat_RcScanLine(
  362. pImageBuffer,
  363. ULONG( pBIH->biHeight - y - 1 ),
  364. nScanLineSize
  365. );
  366. COLORREF * ptrSrc = (COLORREF *)pScanLine;
  367. for( x = 0; x < pBIH->biWidth; x++ )
  368. {
  369. if( pBIH->biBitCount == 32 )
  370. {
  371. BYTE nSrcR = GetRValue( (*ptrSrc) );
  372. BYTE nSrcG = GetGValue( (*ptrSrc) );
  373. BYTE nSrcB = GetBValue( (*ptrSrc) );
  374. #define GetAValue__(rgb) ((BYTE)((rgb)>>24))
  375. BYTE nSrcA = GetAValue__( (*ptrSrc) );
  376. (*ptrSrc) = ( RGB( nSrcB, nSrcG, nSrcR ) | ( COLORREF(nSrcA) << 24 ) );
  377. ptrSrc++;
  378. } // pBIH->biBitCount == 32
  379. else
  380. {
  381. ASSERT( pBIH->biBitCount == 24 );
  382. LPBYTE ptr = (LPBYTE)ptrSrc;
  383. BYTE nTmp = ptr[0];
  384. ptr[0] = ptr[2];
  385. ptr[2] = nTmp;
  386. ptr += 3;
  387. ptrSrc = (COLORREF *)ptr;
  388. } // else from if( pBIH->biBitCount == 32 )
  389. } // for( x = 0; x < pBIH->biWidth; x++ )
  390. } // for( y = 0; y < pBIH->biHeight; y++ )
  391. return true;
  392. }
  393. } // if( pBIH->biBitCount == 32 || pBIH->biBitCount == 24 )
  394. return false;
  395. }
  396. LPBYTE CExtSkinBitmap::stat_PngLoad(
  397. CArchive & ar,
  398. bool bEnableThrowException
  399. )
  400. {
  401. ASSERT( ar.IsLoading() );
  402. png_structp pCallbackData = NULL;
  403. png_infop pInfoPNG = NULL;
  404. png_uint_32 nWidth, nHeight;
  405. png_colorp pPalettePNG;
  406. INT nColorType, nPaletteSize;
  407. INT nBitDepth, nPixelDepth;
  408. LPBYTE pImageBuffer = NULL;
  409. RGBQUAD * pPalette = NULL;
  410. png_bytepp pRows = NULL;
  411. try
  412. {
  413. BYTE png_check[8];
  414. ar.Read( png_check, 8 );
  415. if( ::png_sig_cmp(
  416. png_check,
  417. (png_size_t)0,
  418. 8
  419. ) != 0
  420. )
  421. ::AfxThrowUserException();
  422. pCallbackData =
  423. ::png_create_read_struct(
  424. PNG_LIBPNG_VER_STRING,
  425. (png_voidp)NULL,
  426. (png_error_ptr)stat_PngCallbackError,
  427. (png_error_ptr)stat_PngCallbackWarning
  428. );
  429. if( ! pCallbackData )
  430. ::AfxThrowUserException();
  431. pInfoPNG = ::png_create_info_struct( pCallbackData );
  432. if( ! pInfoPNG )
  433. {
  434. ::png_destroy_read_struct(
  435. &pCallbackData,
  436. (png_infopp)NULL,
  437. (png_infopp)NULL
  438. );
  439. ::AfxThrowUserException();
  440. }
  441. ::png_set_read_fn(
  442. pCallbackData,
  443. &ar,
  444. (png_rw_ptr)stat_PngCallbackRead
  445. );
  446. // disable warning 4611
  447. #pragma warning( push )
  448. #pragma warning ( disable : 4611 )
  449.         if( setjmp( png_jmpbuf( pCallbackData ) ) )
  450. {
  451. ::png_destroy_read_struct(
  452. &pCallbackData,
  453. &pInfoPNG,
  454. NULL
  455. );
  456. ::AfxThrowUserException();
  457. }
  458. // rollback warning 4611
  459. #pragma warning( pop )
  460. ::png_set_sig_bytes( pCallbackData, 8 );
  461. ::png_read_info( pCallbackData, pInfoPNG );
  462. ::png_get_IHDR(
  463. pCallbackData,
  464. pInfoPNG,
  465. &nWidth,
  466. &nHeight,
  467. &nBitDepth,
  468. &nColorType,
  469. NULL,
  470. NULL,
  471. NULL
  472. );
  473. nPixelDepth = pInfoPNG->pixel_depth;
  474. bool bAllocRGB = true;
  475. if( nBitDepth == 16 )
  476. {
  477. if( nPixelDepth == 16
  478. && nColorType == PNG_COLOR_TYPE_GRAY
  479. )
  480. bAllocRGB = false;
  481. else if( nPixelDepth == 48
  482. && nColorType == PNG_COLOR_TYPE_RGB
  483. )
  484. bAllocRGB = false;
  485. else
  486. {
  487. ::png_set_strip_16( pCallbackData );
  488. nBitDepth = 8;
  489. }
  490. } // if( nBitDepth == 16 )
  491. switch( nColorType )
  492. {
  493. case PNG_COLOR_TYPE_RGB:
  494. case PNG_COLOR_TYPE_RGB_ALPHA:
  495. break;
  496. case PNG_COLOR_TYPE_PALETTE:
  497. if( nPixelDepth == 2 )
  498. {
  499. ::png_set_packing( pCallbackData );
  500. nPixelDepth = 8;
  501. }
  502. break;
  503. case PNG_COLOR_TYPE_GRAY:
  504. if( nPixelDepth == 2 )
  505. {
  506. ::png_set_expand( pCallbackData );
  507. nPixelDepth = 8;
  508. }
  509. break;
  510. case PNG_COLOR_TYPE_GRAY_ALPHA:
  511. ::png_set_gray_to_rgb( pCallbackData );
  512. nPixelDepth = 32;
  513. break;
  514. default:
  515. ::AfxThrowUserException();
  516. } // switch( nColorType )
  517. ::png_read_update_info( pCallbackData, pInfoPNG );
  518. nColorType = ::png_get_color_type( pCallbackData, pInfoPNG );
  519. switch( nColorType )
  520. {
  521. case PNG_COLOR_TYPE_RGB:
  522. ::png_set_invert_alpha( pCallbackData );
  523. if( bAllocRGB )
  524. pImageBuffer =
  525. stat_AllocHL(
  526. nWidth,
  527. nHeight,
  528. 24,
  529. 0x00FF0000,
  530. 0x0000FF00,
  531. 0x000000FF,
  532. 0,
  533. 0
  534. );
  535. else
  536. pImageBuffer =
  537. stat_AllocHL(
  538. nWidth,
  539. nHeight,
  540. nPixelDepth,
  541. 0,
  542. 0,
  543. 0,
  544. 0,
  545. 0
  546. );
  547. break;
  548. case PNG_COLOR_TYPE_RGB_ALPHA:
  549. pImageBuffer =
  550. stat_AllocHL(
  551. nWidth,
  552. nHeight,
  553. 32,
  554. 0x00FF0000,
  555. 0x0000FF00,
  556. 0x000000FF,
  557. 0xFF000000,
  558. 0
  559. );
  560. break;
  561. case PNG_COLOR_TYPE_PALETTE:
  562. {
  563. pImageBuffer =
  564. stat_AllocHL(
  565. nWidth,
  566. nHeight,
  567. nPixelDepth,
  568. 0,
  569. 0,
  570. 0,
  571. 0,
  572. 0
  573. );
  574. ::png_get_PLTE(
  575. pCallbackData,
  576. pInfoPNG,
  577. &pPalettePNG,
  578. &nPaletteSize
  579. );
  580. pPalette = ( RGBQUAD * )
  581. ( pImageBuffer + sizeof( BITMAPINFOHEADER ) );
  582. INT nPaletteIndex;
  583. for( nPaletteIndex = 0; nPaletteIndex < nPaletteSize; nPaletteIndex++ )
  584. {
  585. pPalette[nPaletteIndex].rgbRed   = pPalettePNG[nPaletteIndex].red;
  586. pPalette[nPaletteIndex].rgbGreen = pPalettePNG[nPaletteIndex].green;
  587. pPalette[nPaletteIndex].rgbBlue  = pPalettePNG[nPaletteIndex].blue;
  588. } // for( nPaletteIndex = 0; nPaletteIndex < nPaletteSize; nPaletteIndex++ )
  589. }
  590. break;
  591. case PNG_COLOR_TYPE_GRAY:
  592. pImageBuffer =
  593. stat_AllocHL(
  594. nWidth,
  595. nHeight,
  596. nPixelDepth,
  597. 0,
  598. 0,
  599. 0,
  600. 0,
  601. 0
  602. );
  603. if( nPixelDepth <= 8 )
  604. {
  605. pPalette = ( RGBQUAD * )
  606. ( pImageBuffer + sizeof( BITMAPINFOHEADER ) );
  607. nPaletteSize = 1 << nPixelDepth;
  608. INT nPaletteIndex;
  609. for( nPaletteIndex = 0; nPaletteIndex < nPaletteSize; nPaletteIndex++ )
  610. {
  611. pPalette[nPaletteIndex].rgbRed
  612. = pPalette[nPaletteIndex].rgbGreen
  613. = pPalette[nPaletteIndex].rgbBlue
  614. = BYTE( ( nPaletteIndex * 255 ) / ( nPaletteSize - 1 ) );
  615. } // for( nPaletteIndex = 0; nPaletteIndex < nPaletteSize; nPaletteIndex++ )
  616. } // if( nPixelDepth <= 8 )
  617. break;
  618. default:
  619. ::AfxThrowUserException();
  620. } // switch( nColorType )
  621. LPBITMAPINFOHEADER pBIH = stat_RcInfoHeader( pImageBuffer );
  622. if( ::png_get_valid( pCallbackData, pInfoPNG, PNG_INFO_pHYs ) )
  623. {
  624. png_uint_32 nWidthPNG, nHeightPNG;
  625. int res_unit_type = 0;
  626. ::png_get_pHYs(
  627. pCallbackData,
  628. pInfoPNG,
  629. &nWidthPNG,
  630. &nHeightPNG,
  631. &res_unit_type
  632. );
  633. if( res_unit_type == 1 )
  634. {
  635. pBIH->biXPelsPerMeter = nWidthPNG;
  636. pBIH->biYPelsPerMeter = nHeightPNG;
  637. }
  638. } // if( ::png_get_valid( pCallbackData, pInfoPNG, PNG_INFO_pHYs ) )
  639. pRows = ( png_bytepp ) ::malloc( nHeight * sizeof(png_bytep) );
  640. if( ! pRows )
  641. {
  642. if( pPalette != NULL )
  643. ::png_free( pCallbackData, pPalette );
  644. ::png_destroy_read_struct(
  645. &pCallbackData,
  646. &pInfoPNG,
  647. NULL
  648. );
  649. stat_FreeHL( pImageBuffer );
  650. pImageBuffer = NULL;
  651. ::AfxThrowUserException();
  652. } // if( ! pRows )
  653. png_uint_32 nRow;
  654. for( nRow = 0; nRow < nHeight; nRow++)
  655. pRows[nHeight - 1 - nRow] =
  656. stat_RcScanLine(
  657. pImageBuffer,
  658. stat_RcScanLineSize(
  659. nWidth,
  660. pBIH->biBitCount
  661. ),
  662. nRow
  663. );
  664. ::png_read_image( pCallbackData, pRows );
  665. if( pRows )
  666. {
  667. ::free( pRows );
  668. pRows = NULL;
  669. }
  670. ::png_read_end( pCallbackData, pInfoPNG );
  671. if( pCallbackData )
  672. ::png_destroy_read_struct(
  673. &pCallbackData,
  674. &pInfoPNG,
  675. (png_infopp)NULL
  676. );
  677. stat_PngCheckSwap32( pImageBuffer );
  678. return pImageBuffer;
  679. } // try
  680. catch( CException * pException )
  681. {
  682. if( pCallbackData )
  683. ::png_destroy_read_struct(
  684. &pCallbackData,
  685. &pInfoPNG,
  686. (png_infopp)NULL
  687. );
  688. if( pRows )
  689. ::free( pRows );
  690. if( pImageBuffer )
  691. stat_FreeHL( pImageBuffer );
  692. if( bEnableThrowException )
  693. throw;
  694. pException->Delete();
  695. } // catch( CException * pException )
  696. catch( ... )
  697. {
  698. if( pCallbackData )
  699. ::png_destroy_read_struct(
  700. &pCallbackData,
  701. &pInfoPNG,
  702. (png_infopp)NULL
  703. );
  704. if( pRows )
  705. ::free( pRows );
  706. if( pImageBuffer )
  707. stat_FreeHL( pImageBuffer );
  708. if( bEnableThrowException )
  709. ::AfxThrowUserException();
  710. } // catch( ... )
  711. return NULL;
  712. }
  713. bool CExtSkinBitmap::stat_PngSave(
  714. LPBYTE pImageBuffer,
  715. CArchive & ar,
  716. bool bEnableThrowException
  717. )
  718. {
  719. ASSERT( pImageBuffer != NULL );
  720. ASSERT( ar.IsStoring() );
  721. png_structp pCallbackData = NULL;
  722. png_infop pInfoPNG = NULL;
  723. bool bCheckSwap32 = false;
  724. try
  725. {
  726. LPBITMAPINFOHEADER pBIH = stat_RcInfoHeader( pImageBuffer );
  727. if( pBIH->biBitCount != 32
  728. || stat_MaskAlpha( pImageBuffer ) == 0
  729. )
  730. ::AfxThrowUserException(); // not supported
  731. bCheckSwap32 = stat_PngCheckSwap32( pImageBuffer );
  732. INT nBitDepth = (pBIH->biBitCount > 8) ? 8 : pBIH->biBitCount;
  733. png_uint_32 nWidth = pBIH->biWidth;
  734. png_uint_32 nHeight = pBIH->biHeight;
  735. pCallbackData =
  736. ::png_create_write_struct(
  737. PNG_LIBPNG_VER_STRING,
  738. (png_voidp)NULL,
  739. (png_error_ptr)stat_PngCallbackError,
  740. (png_error_ptr)stat_PngCallbackWarning
  741. );
  742. if( ! pCallbackData )
  743. ::AfxThrowUserException();
  744. pInfoPNG = ::png_create_info_struct( pCallbackData );
  745. if( ! pInfoPNG )
  746. {
  747. ::png_destroy_write_struct(&pCallbackData,  (png_infopp)NULL);
  748. ::AfxThrowUserException();
  749. }
  750. // disable warning 4611
  751. #pragma warning( push )
  752. #pragma warning ( disable : 4611 )
  753. if( setjmp( png_jmpbuf( pCallbackData ) ) )
  754. {
  755. ::png_destroy_write_struct( &pCallbackData, &pInfoPNG );
  756. ::AfxThrowUserException();
  757. }
  758. // rollback warning 4611
  759. #pragma warning( pop )
  760. ::png_set_write_fn(
  761. pCallbackData,
  762. &ar,
  763. (png_rw_ptr)stat_PngCallbackWrite,
  764. (png_flush_ptr)stat_PngCallbackFlush
  765. );
  766. if( pBIH->biXPelsPerMeter > 0
  767. && pBIH->biXPelsPerMeter > 0
  768. )
  769. ::png_set_pHYs(
  770. pCallbackData,
  771. pInfoPNG,
  772. png_uint_32(pBIH->biXPelsPerMeter),
  773. png_uint_32(pBIH->biYPelsPerMeter),
  774. 1
  775. );
  776. ::png_set_IHDR(
  777. pCallbackData,
  778. pInfoPNG,
  779. nWidth,
  780. nHeight,
  781. nBitDepth, 
  782. PNG_COLOR_TYPE_RGBA,
  783. PNG_INTERLACE_NONE, 
  784. PNG_COMPRESSION_TYPE_BASE,
  785. PNG_FILTER_TYPE_BASE
  786. );
  787. ::png_write_info( pCallbackData, pInfoPNG );
  788. png_uint_32 nRow;
  789. for( nRow = 0; nRow < nHeight; nRow++ )
  790. {
  791. ::png_write_row(
  792. pCallbackData,
  793. stat_RcScanLine(
  794. pImageBuffer,
  795. stat_RcScanLineSize(
  796. nWidth,
  797. pBIH->biBitCount
  798. ),
  799. nHeight - nRow - 1
  800. )
  801. );
  802. }
  803. ::png_write_end( pCallbackData, pInfoPNG );
  804. ::png_destroy_write_struct( &pCallbackData, &pInfoPNG );
  805. if( bCheckSwap32 )
  806. stat_PngCheckSwap32( pImageBuffer );
  807. return true;
  808. } // try
  809. catch( CException * pException )
  810. {
  811. if( bCheckSwap32 )
  812. stat_PngCheckSwap32( pImageBuffer );
  813. if( pCallbackData )
  814. ::png_destroy_write_struct( &pCallbackData, &pInfoPNG );
  815. if( bEnableThrowException )
  816. throw;
  817. pException->Delete();
  818. } // catch( CException * pException )
  819. catch( ... )
  820. {
  821. if( bCheckSwap32 )
  822. stat_PngCheckSwap32( pImageBuffer );
  823. if( pCallbackData )
  824. ::png_destroy_write_struct( &pCallbackData, &pInfoPNG );
  825. if( bEnableThrowException )
  826. ::AfxThrowUserException();
  827. } // catch( ... )
  828. return false;
  829. }