00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "precomp.h"
00028 #include "PngImage.h"
00029
00030 #include <sys/stat.h>
00031 #include <fcntl.h>
00032 #include <io.h>
00033 #include <share.h>
00034
00038 PngImage::PngImage() : m_pData(NULL), m_nWidth(0), m_nHeight(0), m_nBitsPerPixel(0), m_nBytesPerRow(0)
00039 {
00040 }
00041
00046 PngImage::PngImage(LPCTSTR lpFilename, bool bForce8Bit ) : m_pData(NULL), m_nWidth(0), m_nHeight(0), m_nBitsPerPixel(0), m_nBytesPerRow(0)
00047 {
00048
00049 LoadFromFile(lpFilename, bForce8Bit);
00050 }
00051
00058 PngImage::PngImage(UINT uResourceID, bool bForce8Bit , HMODULE hModule , LPCTSTR lpType ) : m_pData(NULL), m_nWidth(0), m_nHeight(0), m_nBitsPerPixel(0), m_nBytesPerRow(0)
00059 {
00060
00061 LoadFromResource(uResourceID, bForce8Bit, hModule, lpType);
00062 }
00063
00070 bool PngImage::LoadFromFile(LPCTSTR lpFilename, bool bForce8Bit , bool bLeaveGray )
00071 {
00072
00073
00074
00075 struct _stat st;
00076 if (_tstat(lpFilename, &st) != 0)
00077
00078 return false;
00079
00080 if (st.st_mode & _S_IFDIR)
00081
00082 return false;
00083
00084 DWORD dwSize = st.st_size;
00085
00086
00087 int nFile;
00088 if (0 != _tsopen_s(&nFile, lpFilename, _O_BINARY | _O_RDONLY, _SH_DENYNO, _S_IREAD | _S_IWRITE))
00089
00090 return false;
00091
00092
00093 char* pBuffer = new char[dwSize];
00094
00095 if (_read(nFile, pBuffer, dwSize) != (int)dwSize)
00096 {
00097
00098 delete [] pBuffer;
00099 _close(nFile);
00100 return false;
00101 }
00102
00103
00104 _close(nFile);
00105
00106
00107 bool bRet = LoadFromBuffer(pBuffer, dwSize, bForce8Bit, bLeaveGray);
00108
00109
00110 delete [] pBuffer;
00111 return bRet;
00112 }
00113
00122 bool PngImage::LoadFromResource(UINT uResourceID, bool bForce8Bit , HMODULE hModule , LPCTSTR lpType , bool bLeaveGray )
00123 {
00124
00125 HRSRC hResource = FindResource(hModule, MAKEINTRESOURCE(uResourceID), lpType);
00126 if (hResource == NULL)
00127
00128 return false;
00129
00130
00131 DWORD dwSize = SizeofResource(hModule, hResource);
00132 if (dwSize == 0)
00133
00134 return false;
00135
00136
00137 HGLOBAL hData = LoadResource(hModule, hResource);
00138 if (hData == NULL)
00139 return false;
00140 LPVOID lpData = LockResource(hData);
00141 if (lpData == NULL)
00142 return false;
00143
00144
00145 return LoadFromBuffer((const char*)lpData, dwSize, bForce8Bit, bLeaveGray);
00146 }
00147
00151 struct PngReadInfo
00152 {
00153
00158 PngReadInfo(const char* p, DWORD dw) : pBuffer(p), dwLen(dw) {};
00159
00160
00162 const char* pBuffer;
00164 DWORD dwLen;
00165 };
00166
00172 void PNGAPI PngImage::StaticRead(png_structp pPng, png_bytep pBuffer, png_size_t nSize)
00173 {
00174
00175 PngReadInfo* pInfo = (PngReadInfo*)png_get_io_ptr(pPng);
00176 if (pInfo == NULL)
00177 png_error(pPng, "StaticRead error 1");
00178 if (nSize > pInfo->dwLen)
00179 png_error(pPng, "Not enough input");
00180
00181
00182 memcpy(pBuffer, pInfo->pBuffer, nSize);
00183
00184
00185 pInfo->pBuffer += nSize;
00186 pInfo->dwLen -= (DWORD)nSize;
00187 }
00188
00196 bool PngImage::LoadFromBuffer(const char* pBuffer, DWORD dwLen, bool bForce8Bit , bool bLeaveGray )
00197 {
00198
00199 clear();
00200 if (dwLen < 8)
00201 return false;
00202
00203
00204 if (!png_check_sig((png_bytep)pBuffer, 8))
00205 return false;
00206
00207 pBuffer += 8;
00208 dwLen -= 8;
00209
00210
00211 png_structp pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00212 if (pPng == NULL)
00213 return false;
00214
00215
00216 png_infop pPngInfo = png_create_info_struct(pPng);
00217 if (pPngInfo == NULL)
00218 {
00219 png_destroy_read_struct(&pPng, NULL, NULL);
00220 return false;
00221 }
00222
00223 png_infop pPngEndInfo = png_create_info_struct(pPng);
00224 if (pPngEndInfo == NULL)
00225 {
00226 png_destroy_read_struct(&pPng, &pPngInfo, NULL);
00227 return false;
00228 }
00229
00230 if (setjmp(png_jmpbuf(pPng)))
00231 {
00232
00233 png_destroy_read_struct(&pPng, &pPngInfo, &pPngEndInfo);
00234 return false;
00235 }
00236
00237 try
00238 {
00239
00240 PngReadInfo info(pBuffer, dwLen);
00241 png_set_read_fn(pPng, &info, StaticRead);
00242
00243 png_set_sig_bytes(pPng, 8);
00244 png_read_info(pPng, pPngInfo);
00245
00246 int bitDepth, colorType;
00247 ULONG width, height;
00248 png_get_IHDR(pPng, pPngInfo, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL);
00249
00250 m_nWidth = width;
00251 m_nHeight = height;
00252
00253
00254 if (colorType == PNG_COLOR_TYPE_PALETTE)
00255 png_set_palette_to_rgb(pPng);
00256 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)
00257 png_set_gray_1_2_4_to_8(pPng);
00258 if (png_get_valid(pPng, pPngInfo, PNG_INFO_tRNS))
00259 png_set_tRNS_to_alpha(pPng);
00260
00261 if (bitDepth == 16)
00262 {
00263 if(bForce8Bit)
00264 png_set_strip_16(pPng);
00265 else
00266 png_set_swap(pPng);
00267 }
00268
00269 if (bForce8Bit)
00270 bitDepth = 8;
00271
00272 int byteDepth = bitDepth/8;
00273
00274 if (colorType & PNG_COLOR_MASK_ALPHA)
00275 png_set_strip_alpha(pPng);
00276
00277 if (((colorType == PNG_COLOR_TYPE_GRAY) || (colorType == PNG_COLOR_TYPE_GRAY_ALPHA)) && !bLeaveGray)
00278 png_set_gray_to_rgb(pPng);
00279
00280 png_read_update_info(pPng, pPngInfo);
00281
00282
00283
00284 m_nBytesPerRow = png_get_rowbytes(pPng, pPngInfo);
00285 m_nBitsPerPixel = (m_nBytesPerRow / m_nWidth) * bitDepth;
00286
00287 m_pData = new BYTE[m_nBytesPerRow * m_nHeight];
00288 BYTE** pRowPointers = new BYTE*[m_nHeight];
00289 for (int i = 0; i < m_nHeight; ++i)
00290 pRowPointers[i] = m_pData + i*m_nBytesPerRow;
00291
00292
00293 png_read_image(pPng, pRowPointers);
00294 png_read_end(pPng, pPngEndInfo);
00295 png_destroy_read_struct(&pPng, &pPngInfo, &pPngEndInfo);
00296
00297 delete [] pRowPointers;
00298 }
00299 catch(...)
00300 {
00301
00302 clear();
00303 return false;
00304 }
00305
00306
00307 return true;
00308 }
00309
00313 void PngImage::clear()
00314 {
00315 if (m_pData != NULL)
00316 {
00317 delete [] m_pData;
00318 m_pData = NULL;
00319 }
00320 }
00321
00326 HBITMAP PngImage::ToBitmap(HDC hDC)
00327 {
00328
00329 if (m_pData == NULL)
00330
00331 return NULL;
00332
00333
00334 BITMAPINFO info;
00335 info.bmiHeader.biSize = sizeof(info);
00336 info.bmiHeader.biWidth = m_nWidth;
00337 info.bmiHeader.biHeight = -m_nHeight;
00338 info.bmiHeader.biPlanes = 1;
00339 info.bmiHeader.biBitCount = m_nBitsPerPixel;
00340 info.bmiHeader.biCompression = BI_RGB;
00341 info.bmiHeader.biSizeImage = 0;
00342 info.bmiHeader.biXPelsPerMeter = (long)(72 * 100 / 2.56);
00343 info.bmiHeader.biYPelsPerMeter = (long)(72 * 100 / 2.56);
00344 info.bmiHeader.biClrUsed = 0;
00345 info.bmiHeader.biClrImportant = 0;
00346
00347
00348 HBITMAP hBmp = CreateCompatibleBitmap(hDC, m_nWidth, m_nHeight);
00349
00350 SetDIBits(hDC, hBmp, 0, m_nHeight, m_pData, &info, DIB_RGB_COLORS);
00351
00352
00353 return hBmp;
00354 }