X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=image_png.c;h=6b226af060d7f4f1eb85276a1ca3f8b08216757c;hp=b97e9c6d04dfd5bb9f5092916fd02dafc24657fe;hb=91342dd0a88d002a188418a4b0dd21957e0737b6;hpb=c3edd749ac26c6322eafa8303e592df3c32ffd25 diff --git a/image_png.c b/image_png.c index b97e9c6d..6b226af0 100644 --- a/image_png.c +++ b/image_png.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2006 Serge "(515)" Ziryukin, Forest "LordHavoc" Hale + Copyright (C) 2006 Serge "(515)" Ziryukin, Ashley Rose Hale (LadyHavoc) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -24,12 +24,13 @@ //[515]: png implemented into DP ONLY FOR TESTING 2d stuff with csqc // so delete this bullshit :D // -//LordHavoc: rewrote most of this. +//LadyHavoc: rewrote most of this. -#include "quakedef.h" +#include "darkplaces.h" #include "image.h" #include "image_png.h" + static void (*qpng_set_sig_bytes) (void*, int); static int (*qpng_sig_cmp) (const unsigned char*, size_t, size_t); static void* (*qpng_create_read_struct) (const char*, void*, void(*)(void *png, const char *message), void(*)(void *png, const char *message)); @@ -39,7 +40,6 @@ static void (*qpng_read_info) (void*, void*); static void (*qpng_set_compression_level) (void*, int); static void (*qpng_set_filter) (void*, int, int); static void (*qpng_set_expand) (void*); -static void (*qpng_set_gray_1_2_4_to_8) (void*); static void (*qpng_set_palette_to_rgb) (void*); static void (*qpng_set_tRNS_to_alpha) (void*); static void (*qpng_set_gray_to_rgb) (void*); @@ -60,11 +60,23 @@ static unsigned int (*qpng_get_rowbytes) (void*, void*); static unsigned char (*qpng_get_channels) (void*, void*); static unsigned char (*qpng_get_bit_depth) (void*, void*); static unsigned int (*qpng_get_IHDR) (void*, void*, unsigned long*, unsigned long*, int *, int *, int *, int *, int *); -static char* (*qpng_get_libpng_ver) (void*); +static unsigned int (*qpng_access_version_number) (void); // FIXME is this return type right? It is a png_uint_32 in libpng static void (*qpng_write_info) (void*, void*); static void (*qpng_write_row) (void*, unsigned char*); static void (*qpng_write_end) (void*, void*); +// libpng 1.4+ longjmp hack +typedef void (*qpng_longjmp_ptr) (jmp_buf, int); +static jmp_buf* (*qpng_set_longjmp_fn) (void *, qpng_longjmp_ptr, size_t); +#define qpng_jmpbuf_14(png_ptr) (*qpng_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) + +// libpng 1.2 longjmp hack +#define qpng_jmpbuf_12(png_ptr) (*((jmp_buf *) png_ptr)) + +// all version support +#define qpng_jmpbuf(png_ptr) \ + (qpng_set_longjmp_fn ? qpng_jmpbuf_14(png_ptr) : qpng_jmpbuf_12(png_ptr)) + static dllfunction_t pngfuncs[] = { {"png_set_sig_bytes", (void **) &qpng_set_sig_bytes}, @@ -76,7 +88,6 @@ static dllfunction_t pngfuncs[] = {"png_set_compression_level", (void **) &qpng_set_compression_level}, {"png_set_filter", (void **) &qpng_set_filter}, {"png_set_expand", (void **) &qpng_set_expand}, - {"png_set_gray_1_2_4_to_8", (void **) &qpng_set_gray_1_2_4_to_8}, {"png_set_palette_to_rgb", (void **) &qpng_set_palette_to_rgb}, {"png_set_tRNS_to_alpha", (void **) &qpng_set_tRNS_to_alpha}, {"png_set_gray_to_rgb", (void **) &qpng_set_gray_to_rgb}, @@ -97,15 +108,21 @@ static dllfunction_t pngfuncs[] = {"png_get_channels", (void **) &qpng_get_channels}, {"png_get_bit_depth", (void **) &qpng_get_bit_depth}, {"png_get_IHDR", (void **) &qpng_get_IHDR}, - {"png_get_libpng_ver", (void **) &qpng_get_libpng_ver}, + {"png_access_version_number", (void **) &qpng_access_version_number}, {"png_write_info", (void **) &qpng_write_info}, {"png_write_row", (void **) &qpng_write_row}, {"png_write_end", (void **) &qpng_write_end}, {NULL, NULL} }; +static dllfunction_t png14funcs[] = +{ + {"png_set_longjmp_fn", (void **) &qpng_set_longjmp_fn}, + {NULL, NULL} +}; // Handle for PNG DLL dllhandle_t png_dll = NULL; +dllhandle_t png14_dll = NULL; /* @@ -123,15 +140,27 @@ PNG_OpenLibrary Try to load the PNG DLL ==================== */ -qboolean PNG_OpenLibrary (void) +qbool PNG_OpenLibrary (void) { const char* dllnames [] = { #if WIN32 + "libpng16.dll", + "libpng16-16.dll", + "libpng15-15.dll", + "libpng15.dll", + "libpng14-14.dll", + "libpng14.dll", "libpng12.dll", #elif defined(MACOSX) + "libpng16.16.dylib", + "libpng15.15.dylib", + "libpng14.14.dylib", "libpng12.0.dylib", #else + "libpng16.so.16", + "libpng15.so.15", // WTF libtool guidelines anyone? + "libpng14.so.14", // WTF libtool guidelines anyone? "libpng12.so.0", "libpng.so", // FreeBSD #endif @@ -143,7 +172,15 @@ qboolean PNG_OpenLibrary (void) return true; // Load the DLL - return Sys_LoadLibrary (dllnames, &png_dll, pngfuncs); + if(!Sys_LoadDependency (dllnames, &png_dll, pngfuncs)) + return false; + if(qpng_access_version_number() / 100 >= 104) + if(!Sys_LoadDependency (dllnames, &png14_dll, png14funcs)) + { + Sys_FreeLibrary (&png_dll); + return false; + } + return true; } @@ -156,7 +193,8 @@ Unload the PNG DLL */ void PNG_CloseLibrary (void) { - Sys_UnloadLibrary (&png_dll); + Sys_FreeLibrary (&png14_dll); + Sys_FreeLibrary (&png_dll); } /* @@ -167,7 +205,10 @@ void PNG_CloseLibrary (void) ================================================================= */ -#define PNG_LIBPNG_VER_STRING "1.2.4" +#define PNG_LIBPNG_VER_STRING_12 "1.2.4" +#define PNG_LIBPNG_VER_STRING_14 "1.4.0" +#define PNG_LIBPNG_VER_STRING_15 "1.5.0" +#define PNG_LIBPNG_VER_STRING_16 "1.6.0" #define PNG_COLOR_MASK_PALETTE 1 #define PNG_COLOR_MASK_COLOR 2 @@ -213,8 +254,8 @@ static struct qfile_t *outfile; } my_png; -//LordHavoc: removed __cdecl prefix, added overrun protection, and rewrote this to be more efficient -void PNG_fReadData(void *png, unsigned char *data, size_t length) +//LadyHavoc: removed __cdecl prefix, added overrun protection, and rewrote this to be more efficient +static void PNG_fReadData(void *png, unsigned char *data, size_t length) { size_t l; l = my_png.tmpBuflength - my_png.tmpi; @@ -231,29 +272,26 @@ void PNG_fReadData(void *png, unsigned char *data, size_t length) //Com_HexDumpToConsole(data, (int)length); } -void PNG_fWriteData(void *png, unsigned char *data, size_t length) +static void PNG_fWriteData(void *png, unsigned char *data, size_t length) { FS_Write(my_png.outfile, data, length); } -void PNG_fFlushData(void *png) +static void PNG_fFlushData(void *png) { } -void PNG_error_fn(void *png, const char *message) +static void PNG_error_fn(void *png, const char *message) { - Con_Printf("PNG_LoadImage: error: %s\n", message); + Con_Printf(CON_ERROR "PNG_LoadImage: error: %s\n", message); } -void PNG_warning_fn(void *png, const char *message) +static void PNG_warning_fn(void *png, const char *message) { - Con_Printf("PNG_LoadImage: warning: %s\n", message); + Con_Printf(CON_WARN "PNG_LoadImage: warning: %s\n", message); } -extern int image_width; -extern int image_height; - -unsigned char *PNG_LoadImage_BGRA (const unsigned char *raw, int filesize) +unsigned char *PNG_LoadImage_BGRA (const unsigned char *raw, int filesize, int *miplevel) { unsigned int c; unsigned int y; @@ -269,7 +307,13 @@ unsigned char *PNG_LoadImage_BGRA (const unsigned char *raw, int filesize) if(qpng_sig_cmp(raw, 0, filesize)) return NULL; - png = (void *)qpng_create_read_struct(PNG_LIBPNG_VER_STRING, 0, PNG_error_fn, PNG_warning_fn); + png = (void *)qpng_create_read_struct( + (qpng_access_version_number() / 100 == 102) ? PNG_LIBPNG_VER_STRING_12 : + (qpng_access_version_number() / 100 == 104) ? PNG_LIBPNG_VER_STRING_14 : + (qpng_access_version_number() / 100 == 105) ? PNG_LIBPNG_VER_STRING_15 : + PNG_LIBPNG_VER_STRING_16, // nasty hack... whatever + 0, PNG_error_fn, PNG_warning_fn + ); if(!png) return NULL; @@ -279,15 +323,7 @@ unsigned char *PNG_LoadImage_BGRA (const unsigned char *raw, int filesize) // 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 -#if defined(MACOSX) || defined(WIN32) - if (setjmp((int *)png)) -#else - if (setjmp((__jmp_buf_tag *)png)) -#endif -#else - if (setjmp(png)) -#endif + if (setjmp(qpng_jmpbuf(png))) { if (my_png.Data) Mem_Free(my_png.Data); @@ -339,12 +375,7 @@ unsigned char *PNG_LoadImage_BGRA (const unsigned char *raw, int filesize) if (my_png.ColorType == PNG_COLOR_TYPE_PALETTE) qpng_set_palette_to_rgb(png); if (my_png.ColorType == PNG_COLOR_TYPE_GRAY || my_png.ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) - { qpng_set_gray_to_rgb(png); - if (my_png.BitDepth < 8) - qpng_set_gray_1_2_4_to_8(png); - } - if (qpng_get_valid(png, pnginfo, PNG_INFO_tRNS)) qpng_set_tRNS_to_alpha(png); if (my_png.BitDepth == 8 && !(my_png.ColorType & PNG_COLOR_MASK_ALPHA)) @@ -443,7 +474,7 @@ 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) +qbool PNG_SaveImage_preflipped (const char *filename, int width, int height, qbool has_alpha, unsigned char *data) { unsigned int offset, linesize; qfile_t* file = NULL; @@ -458,7 +489,13 @@ qboolean PNG_SaveImage_preflipped (const char *filename, int width, int height, return false; } - png = (void *)qpng_create_write_struct(PNG_LIBPNG_VER_STRING, 0, PNG_error_fn, PNG_warning_fn); + png = (void *)qpng_create_write_struct( + (qpng_access_version_number() / 100 == 102) ? PNG_LIBPNG_VER_STRING_12 : + (qpng_access_version_number() / 100 == 104) ? PNG_LIBPNG_VER_STRING_14 : + (qpng_access_version_number() / 100 == 105) ? PNG_LIBPNG_VER_STRING_15 : + PNG_LIBPNG_VER_STRING_16, // nasty hack... whatever + 0, PNG_error_fn, PNG_warning_fn + ); if(!png) return false; pnginfo = (void *)qpng_create_info_struct(png); @@ -474,14 +511,14 @@ qboolean PNG_SaveImage_preflipped (const char *filename, int width, int height, // 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 -#if defined(MACOSX) || defined(WIN32) +#ifdef WIN64 + if (setjmp((_JBTYPE *)png)) +#elif defined(MACOSX) || defined(WIN32) if (setjmp((int *)png)) +#elif defined(__ANDROID__) + if (setjmp((long *)png)) #else - if (setjmp((__jmp_buf_tag *)png)) -#endif -#else - if (setjmp(png)) + if (setjmp((struct __jmp_buf_tag *)png)) #endif { qpng_destroy_write_struct(&png, &pnginfo);