XTPGraphicBitmapPng.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:8k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPGraphicBitmapPng.cpp : implementation of the CXTPGraphicBitmapPng class.
  2. //
  3. // This file is a part of the XTREME TOOLKITPRO MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "libpngpng.h"
  22. #include "XTPGraphicBitmapPng.h"
  23. //////////////////////////////////////////////////////////////////////////
  24. // CXTPGraphicBitmapPng
  25. CXTPGraphicBitmapPng::CXTPGraphicBitmapPng()
  26. {
  27. m_bAlpha = FALSE;
  28. }
  29. static void PNGAPI png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
  30. {
  31. CFile* pFile = (CFile*)png_ptr->io_ptr;
  32. png_size_t sizeRead = (png_size_t)pFile->Read(data, (UINT)length);
  33. if (sizeRead != length)
  34. {
  35. AfxThrowFileException(CFileException::endOfFile);
  36. }
  37. }
  38. static void png_cexcept_error(png_structp /*png_ptr*/, png_const_charp /*msg*/)
  39. {
  40. AfxThrowFileException(CFileException::badSeek);
  41. }
  42. BOOL PngLoadImage(CFile* pFile, png_byte **ppbImageData,
  43. png_uint_32 *piWidth, png_uint_32 *piHeight, int *piChannels, png_color *pBkgColor)
  44. {
  45. png_byte            pbSig[8];
  46. int                 iBitDepth;
  47. int                 iColorType;
  48. double              dGamma;
  49. png_color_16       *pBackground;
  50. png_uint_32         ulChannels;
  51. png_uint_32         ulRowBytes;
  52. png_byte           *pbImageData = *ppbImageData;
  53. png_byte          **ppbRowPointers = NULL;
  54. png_uint_32         i;
  55. png_structp         png_ptr = NULL;
  56. png_infop           info_ptr = NULL;
  57. // open the PNG input file
  58. if (!pFile)
  59. {
  60. *ppbImageData = pbImageData = NULL;
  61. return FALSE;
  62. }
  63. pFile->Read(pbSig, 8);
  64. if (!png_check_sig(pbSig, 8))
  65. {
  66. *ppbImageData = pbImageData = NULL;
  67. return FALSE;
  68. }
  69. // create the two png(-info) structures
  70. png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
  71. (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
  72. if (!png_ptr)
  73. {
  74. *ppbImageData = pbImageData = NULL;
  75. return FALSE;
  76. }
  77. info_ptr = png_create_info_struct(png_ptr);
  78. if (!info_ptr)
  79. {
  80. png_destroy_read_struct(&png_ptr, NULL, NULL);
  81. *ppbImageData = pbImageData = NULL;
  82. return FALSE;
  83. }
  84. TRY
  85. {
  86. // initialize the png structure
  87. png_set_read_fn(png_ptr, (png_voidp)pFile, png_read_data);
  88. png_set_sig_bytes(png_ptr, 8);
  89. // read all PNG info up to image data
  90. png_read_info(png_ptr, info_ptr);
  91. // get width, height, bit-depth and color-type
  92. png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
  93. &iColorType, NULL, NULL, NULL);
  94. // expand images of all color-type and bit-depth to 3x8 bit RGB images
  95. // let the library process things like alpha, transparency, background
  96. if (iBitDepth == 16)
  97. png_set_strip_16(png_ptr);
  98. if (iColorType == PNG_COLOR_TYPE_PALETTE)
  99. png_set_expand(png_ptr);
  100. if (iBitDepth < 8)
  101. png_set_expand(png_ptr);
  102. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
  103. png_set_expand(png_ptr);
  104. if (iColorType == PNG_COLOR_TYPE_GRAY ||
  105. iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
  106. png_set_gray_to_rgb(png_ptr);
  107. // set the background color to draw transparent and alpha images over.
  108. if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
  109. {
  110. png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
  111. pBkgColor->red   = (byte) pBackground->red;
  112. pBkgColor->green = (byte) pBackground->green;
  113. pBkgColor->blue  = (byte) pBackground->blue;
  114. }
  115. else
  116. {
  117. pBkgColor = NULL;
  118. }
  119. // if required set gamma conversion
  120. if (png_get_gAMA(png_ptr, info_ptr, &dGamma))
  121. png_set_gamma(png_ptr, (double) 2.2, dGamma);
  122. // after the transformations have been registered update info_ptr data
  123. png_read_update_info(png_ptr, info_ptr);
  124. // get again width, height and the new bit-depth and color-type
  125. png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
  126. &iColorType, NULL, NULL, NULL);
  127. // row_bytes is the width x number of channels
  128. ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
  129. ulChannels = png_get_channels(png_ptr, info_ptr);
  130. *piChannels = ulChannels;
  131. // now we can allocate memory to store the image
  132. if (pbImageData)
  133. {
  134. free (pbImageData);
  135. pbImageData = NULL;
  136. }
  137. pbImageData = (png_byte*)malloc(ulRowBytes * (*piHeight) * sizeof(png_byte));
  138. if (pbImageData == NULL)
  139. {
  140. AfxThrowFileException(CFileException::badSeek);
  141. }
  142. *ppbImageData = pbImageData;
  143. // and allocate memory for an array of row-pointers
  144. ppbRowPointers = (png_bytepp)malloc((*piHeight) * sizeof(png_bytep));
  145. if (ppbRowPointers == NULL)
  146. {
  147. AfxThrowFileException(CFileException::badSeek);
  148. }
  149. // set the individual row-pointers to point at the correct offsets
  150. for (i = 0; i < (*piHeight); i++)
  151. ppbRowPointers[i] = pbImageData + i * ulRowBytes;
  152. // now we can go ahead and just read the whole image
  153. png_read_image(png_ptr, ppbRowPointers);
  154. // read the additional chunks in the PNG file (not really needed)
  155. png_read_end(png_ptr, NULL);
  156. // and we're done
  157. free (ppbRowPointers);
  158. ppbRowPointers = NULL;
  159. // yepp, done
  160. }
  161. CATCH (CFileException, e)
  162. {
  163. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  164. *ppbImageData = pbImageData = NULL;
  165. if (ppbRowPointers)
  166. free (ppbRowPointers);
  167. return FALSE;
  168. }
  169. END_CATCH
  170. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  171. return TRUE;
  172. }
  173. HBITMAP CXTPGraphicBitmapPng::ConvertToBitmap(BYTE* pbImage, CSize szImage,  int cImgChannels) const
  174. {
  175. LONG xImg, yImg;
  176. BYTE *src, *dst;
  177. BYTE r, g, b, a;
  178. BITMAPINFO bmi;
  179. LPBYTE pBits;
  180. HBITMAP hbm;
  181. const int cDIChannels = 4;
  182. UINT wImgRowBytes;
  183. UINT wDIRowBytes;
  184. // Initialize header to 0s.
  185. ZeroMemory(&bmi, sizeof(bmi));
  186. // Fill out the fields you care about.
  187. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  188. bmi.bmiHeader.biWidth = szImage.cx;
  189. bmi.bmiHeader.biHeight = -szImage.cy;
  190. bmi.bmiHeader.biPlanes = 1;
  191. bmi.bmiHeader.biBitCount = 32;
  192. bmi.bmiHeader.biCompression = BI_RGB;
  193. hbm = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (LPVOID*)&pBits, NULL, 0);
  194. if (!hbm || !pBits)
  195. {
  196. return NULL;
  197. }
  198. wImgRowBytes = cImgChannels * szImage.cx;
  199. wDIRowBytes = cDIChannels * szImage.cx;
  200. // copy image to screen
  201. for (yImg = 0; yImg < szImage.cy; yImg++)
  202. {
  203. src = pbImage + yImg * wImgRowBytes;
  204. dst = pBits + yImg * wDIRowBytes;
  205. for (xImg = 0; xImg < szImage.cx; xImg++)
  206. {
  207. r = *src++;
  208. g = *src++;
  209. b = *src++;
  210. *dst++ = b;
  211. *dst++ = g;
  212. *dst++ = r;
  213. a = 0;
  214. if (cImgChannels == 4)
  215. {
  216. a = *src++;
  217. }
  218. *dst++ = a;
  219. }
  220. }
  221. return hbm;
  222. }
  223. BOOL CXTPGraphicBitmapPng::LoadFromFile(LPCTSTR lpszFileName)
  224. {
  225. m_bAlpha = FALSE;
  226. DeleteObject();
  227. CFile file;
  228. if (!file.Open(lpszFileName, CFile::modeRead))
  229. {
  230. return FALSE;
  231. }
  232. return LoadFromFile(&file);
  233. }
  234. BOOL CXTPGraphicBitmapPng::LoadFromResource(HMODULE hModule, HRSRC hRes)
  235. {
  236. m_bAlpha = FALSE;
  237. DeleteObject();
  238. if (!hRes)
  239. return FALSE;
  240. DWORD nBufferSize = ::SizeofResource(hModule, hRes);
  241. HGLOBAL hMem= ::LoadResource(hModule, hRes);
  242. if (!hMem)
  243. return FALSE;
  244. LPBYTE lpBuffer = (LPBYTE)LockResource(hMem);
  245. if (!lpBuffer || nBufferSize < 10)
  246. return FALSE;
  247. CMemFile file(lpBuffer, nBufferSize);
  248. return LoadFromFile(&file);
  249. }
  250. BOOL CXTPGraphicBitmapPng::LoadFromFile(CFile* pFile)
  251. {
  252. m_bAlpha = FALSE;
  253. DeleteObject();
  254. BYTE* pbImage = NULL;
  255. png_uint_32 cxImgSize, cyImgSize;
  256. int cImgChannels;
  257. png_color bkgColor =  {127, 127, 127};
  258. if (!pFile)
  259. return FALSE;
  260. if (!PngLoadImage(pFile, &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
  261. {
  262. if (pbImage)
  263. {
  264. free(pbImage);
  265. return FALSE;
  266. }
  267. }
  268. if (!pbImage)
  269. return FALSE;
  270. HBITMAP hBitmap = ConvertToBitmap(pbImage, CSize(cxImgSize, cyImgSize), cImgChannels);
  271. free(pbImage);
  272. if (!hBitmap)
  273. return FALSE;
  274. m_bAlpha = (cImgChannels == 4);
  275. Attach(hBitmap);
  276. return TRUE;
  277. }