25 void PNGAPI CPNGFile::CPNGReadFn(png_structp png_ptr, png_bytep data,
size_t length)
27 static_cast<CPNGFile*
>(png_get_io_ptr(png_ptr))->Read(data, length);
30 void CPNGFile::Read(
unsigned char *pData,
int iLength)
34 memcpy(pData, pFilePtr, iLength);
39 bool CPNGFile::DoLoad()
44 if (png_sig_cmp((
unsigned char *) pFilePtr, 0, 8))
return false;
47 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
48 if (!png_ptr)
return false;
49 info_ptr = png_create_info_struct(png_ptr);
50 if (!info_ptr)
return false;
51 end_info = png_create_info_struct(png_ptr);
52 if (!end_info)
return false;
54 if (setjmp(png_jmpbuf(png_ptr)))
return false;
56 png_set_read_fn(png_ptr,
this, &CPNGFile::CPNGReadFn);
58 png_read_info(png_ptr, info_ptr);
60 png_uint_32 uWdt =
iWdt, uHgt =
iHgt;
63 if (
iClrType == PNG_COLOR_TYPE_PALETTE &&
iBPC <= 8) png_set_expand(png_ptr);
64 if (
iClrType == PNG_COLOR_TYPE_GRAY &&
iBPC < 8) png_set_expand(png_ptr);
65 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr);
66 if (
iBPC == 16) png_set_strip_16(png_ptr);
67 if (
iBPC < 8) png_set_packing(png_ptr);
68 if (
iClrType == PNG_COLOR_TYPE_GRAY ||
iClrType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);
71 png_read_update_info(png_ptr, info_ptr);
77 case PNG_COLOR_TYPE_RGB: iPixSize=3;
break;
78 case PNG_COLOR_TYPE_RGB_ALPHA: iPixSize=4;
break;
79 default:
return false;
82 iRowSize=png_get_rowbytes(png_ptr, info_ptr);
83 pImageData =
new unsigned char[iRowSize*
iHgt];
85 unsigned char **ppRowBuf =
new unsigned char *[
iHgt];
86 unsigned char **ppRows=ppRowBuf;
unsigned char *pRow=pImageData;
87 for (
unsigned int i=0; i<
iHgt; ++i,pRow+=iRowSize) *ppRows++=pRow;
89 png_read_image(png_ptr, ppRowBuf);
108 info_ptr=end_info=
nullptr;
124 if (png_ptr || info_ptr || end_info)
127 png_destroy_write_struct(&png_ptr, &info_ptr);
129 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
132 info_ptr=end_info=
nullptr;
139 if (pImageData) {
delete [] pImageData; pImageData=
nullptr; }
152 if (fp) { fclose(fp); fp=
nullptr; }
170 this->pFile =
nullptr; iFileSize=0;
178 if (!pImageData)
return 0;
180 unsigned char *pPix=pImageData+iY*iRowSize+iX*iPixSize;
183 case PNG_COLOR_TYPE_RGB:
184 return C4RGB(pPix[2], pPix[1], pPix[0]);
185 case PNG_COLOR_TYPE_RGB_ALPHA:
186 return RGBA(pPix[2], pPix[1], pPix[0], pPix[3]);
194 if (
iWdt<=0 ||
iHgt<=0)
return false;
201 iClrType = fAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB;
202 iPixSize = fAlpha ? 4 : 3;
205 iCmprType = PNG_COMPRESSION_TYPE_DEFAULT;
208 int iBPP = (fAlpha ? 4 : 3) *
iBPC;
209 iRowSize = (iBPP*
iWdt+7)>>3;
211 pImageData =
new unsigned char[
iHgt * iRowSize];
219 if (!pImageData)
return false;
221 unsigned char *pPix=pImageData+iY*iRowSize+iX*iPixSize;
224 case PNG_COLOR_TYPE_RGB:
229 case PNG_COLOR_TYPE_RGB_ALPHA:
230 *(
DWORD *) pPix = dwValue;
239 if (!pImageData)
return false;
241 fp = fopen(szFilename,
"wb");
if (!fp)
return false;
246 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
247 if (!png_ptr) {
Clear();
return false; }
248 info_ptr = png_create_info_struct(png_ptr);
249 if (!info_ptr) {
Clear();
return false; }
251 if (setjmp(png_jmpbuf(png_ptr))) {
Clear();
return false; }
253 png_init_io(png_ptr, fp);
255 png_set_filter(png_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_PAETH);
256 png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
257 png_set_compression_mem_level(png_ptr, 8);
258 png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
259 png_set_compression_window_bits(png_ptr, 15);
260 png_set_compression_method(png_ptr, 8);
264 int iRealRowSize=png_get_rowbytes(png_ptr, info_ptr);
265 if (iRealRowSize != iRowSize)
268 Clear();
return false;
271 png_write_info(png_ptr, info_ptr);
273 png_set_bgr(png_ptr);
275 unsigned char **ppRowBuf =
new unsigned char *[
iHgt];
276 unsigned char **ppRows=ppRowBuf;
unsigned char *pRow=pImageData;
277 for (
unsigned int i=0; i<
iHgt; ++i,pRow+=iRowSize) *ppRows++=pRow;
279 png_write_image(png_ptr, ppRowBuf);
283 png_write_end(png_ptr, info_ptr);
285 fclose(fp); fp =
nullptr;
296 case PNG_COLOR_TYPE_RGB:
return 24;
297 case PNG_COLOR_TYPE_RGB_ALPHA:
return 32;
307 std::unique_ptr<CPNGFile> png;
311 static std::list<CPNGSaveThread *> threads;
323 CStdCSec CPNGSaveThread::threads_sec;
324 std::list<CPNGSaveThread *> CPNGSaveThread::threads;
330 threads.push_back(
this);
337 threads.remove(
this);
351 return !threads.empty();
359 if (!saver->
Start())
delete saver;
369 if (first)
LogSilent(
"Waiting for pending image files to be written to disc...");
371 #ifdef HAVE_WINTHREAD
bool LogSilent(const char *szMessage, bool fConsole)
uint32_t RGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
#define GetGreenValue(rgb)
#define GetBlueValue(rgb)
bool Create(int iWdt, int iHgt, bool fAlpha)
bool SetPix(int iX, int iY, DWORD dwValue)
bool Save(const char *szFilename)
static void ScheduleSaving(CPNGFile *png, const char *filename)
bool Load(BYTE *pFile, int iSize)
DWORD GetPix(int iX, int iY)
static void WaitForSaves()
static bool HasPendingThreads()
~CPNGSaveThread() override
CPNGSaveThread(CPNGFile *png, const char *filename)
bool IsSelfDestruct() override
const char * getData() const