+/*
+=================================================================
+
+ PNG compression
+
+=================================================================
+*/
+
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define PNG_INTERLACE_NONE 0
+#define PNG_INTERLACE_ADAM7 1
+#define PNG_FILTER_TYPE_BASE 0
+#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE
+#define PNG_COMPRESSION_TYPE_BASE 0
+#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE
+#define PNG_NO_FILTERS 0x00
+#define PNG_FILTER_NONE 0x08
+#define PNG_FILTER_SUB 0x10
+#define PNG_FILTER_UP 0x20
+#define PNG_FILTER_AVG 0x40
+#define PNG_FILTER_PAETH 0x80
+#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
+ PNG_FILTER_AVG | PNG_FILTER_PAETH)
+
+/*
+====================
+PNG_SaveImage_preflipped
+
+Save a preflipped PNG image to a file
+====================
+*/
+qboolean PNG_SaveImage_preflipped (const char *filename, int width, int height, qboolean has_alpha, unsigned char *data)
+{
+ unsigned int offset, linesize;
+ qfile_t* file = NULL;
+ void *png, *pnginfo;
+ unsigned char ioBuffer[8192];
+ int passes, i, j;
+
+ // No DLL = no JPEGs
+ if (!png_dll)
+ {
+ Con_Print("You need the libpng library to save PNG images\n");
+ return false;
+ }
+
+ png = (void *)qpng_create_write_struct(
+ (qpng_access_version_number() / 100 == 102) ? PNG_LIBPNG_VER_STRING_12 : PNG_LIBPNG_VER_STRING_14, // nasty hack to support both libpng12 and libpng14
+ 0, PNG_error_fn, PNG_warning_fn
+ );
+ if(!png)
+ return false;
+ pnginfo = (void *)qpng_create_info_struct(png);
+ if(!pnginfo)
+ {
+ qpng_destroy_write_struct(&png, NULL);
+ return false;
+ }
+
+ // this must be memset before the setjmp error handler, because it relies
+ // on the fields in this struct for cleanup
+ memset(&my_png, 0, sizeof(my_png));
+
+ // NOTE: this relies on jmp_buf being the first thing in the png structure
+ // created by libpng! (this is correct for libpng 1.2.x)
+#ifdef __cplusplus
+#ifdef WIN64
+ if (setjmp((_JBTYPE *)png))
+#elif defined(MACOSX) || defined(WIN32)
+ if (setjmp((int *)png))
+#else
+ if (setjmp((__jmp_buf_tag *)png))
+#endif
+#else
+ if (setjmp(png))
+#endif
+ {
+ qpng_destroy_write_struct(&png, &pnginfo);
+ return false;
+ }
+
+ // Open the file
+ file = FS_OpenRealFile(filename, "wb", true);
+ if (!file)
+ return false;
+ my_png.outfile = file;
+ qpng_set_write_fn(png, ioBuffer, PNG_fWriteData, PNG_fFlushData);
+
+ //qpng_set_compression_level(png, Z_BEST_COMPRESSION);
+ qpng_set_compression_level(png, Z_BEST_SPEED);
+ qpng_set_IHDR(png, pnginfo, width, height, 8, has_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ qpng_set_filter(png, 0, PNG_NO_FILTERS);
+ qpng_write_info(png, pnginfo);
+ qpng_set_packing(png);
+ qpng_set_bgr(png);
+
+ passes = qpng_set_interlace_handling(png);
+
+ linesize = width * (has_alpha ? 4 : 3);
+ offset = linesize * (height - 1);
+ for(i = 0; i < passes; ++i)
+ for(j = 0; j < height; ++j)
+ qpng_write_row(png, &data[offset - j * linesize]);
+
+ qpng_write_end(png, NULL);
+ qpng_destroy_write_struct(&png, &pnginfo);
+
+ FS_Close (file);
+
+ return true;
+}