/* ==================== PNG_OpenLibrary Try to load the PNG DLL ==================== */ qboolean PNG_OpenLibrary (void) { #ifndef LINK_TO_LIBPNG 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", "libpng16.so.16", "libpng15.so.15", // WTF libtool guidelines anyone? "libpng14.so.14", // WTF libtool guidelines anyone? "libpng12.so.0", "libpng.so", // FreeBSD #endif NULL }; // Already loaded? if (png_dll) return true; // Load the DLL if(!Sys_LoadLibrary (dllnames, &png_dll, pngfuncs)) return false; if(qpng_access_version_number() / 100 >= 104) if(!Sys_LoadLibrary (dllnames, &png14_dll, png14funcs)) { Sys_UnloadLibrary (&png_dll); return false; } #endif return true; }
unsigned char *PNG_LoadImage_BGRA (const unsigned char *raw, int filesize, int *miplevel) { unsigned int c; unsigned int y; void *png, *pnginfo; unsigned char *imagedata = NULL; unsigned char ioBuffer[8192]; // FIXME: register an error handler so that abort() won't be called on error // No DLL = no PNGs if (!png_dll) return NULL; if(qpng_sig_cmp(raw, 0, filesize)) return NULL; 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 : PNG_LIBPNG_VER_STRING_15, // nasty hack... whatever 0, PNG_error_fn, PNG_warning_fn ); if(!png) return NULL; // 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) if (setjmp(qpng_jmpbuf(png))) { if (my_png.Data) Mem_Free(my_png.Data); my_png.Data = NULL; if (my_png.FRowPtrs) Mem_Free(my_png.FRowPtrs); my_png.FRowPtrs = NULL; qpng_destroy_read_struct(&png, &pnginfo, 0); return NULL; } // pnginfo = qpng_create_info_struct(png); if(!pnginfo) { qpng_destroy_read_struct(&png, &pnginfo, 0); return NULL; } qpng_set_sig_bytes(png, 0); my_png.tmpBuf = raw; my_png.tmpBuflength = filesize; my_png.tmpi = 0; //my_png.Data = NULL; //my_png.FRowPtrs = NULL; //my_png.Height = 0; //my_png.Width = 0; my_png.ColorType = PNG_COLOR_TYPE_RGB; //my_png.Interlace = 0; //my_png.Compression = 0; //my_png.Filter = 0; qpng_set_read_fn(png, ioBuffer, PNG_fReadData); qpng_read_info(png, pnginfo); qpng_get_IHDR(png, pnginfo, &my_png.Width, &my_png.Height,&my_png.BitDepth, &my_png.ColorType, &my_png.Interlace, &my_png.Compression, &my_png.Filter); // this check guards against pngconf.h with unsigned int *width/height parameters on big endian systems by detecting the strange values and shifting them down 32bits // (if it's little endian the unwritten bytes are the most significant // ones and we don't worry about that) // // this is only necessary because of retarded 64bit png_uint_32 types in libpng 1.2, which can (conceivably) vary by platform #if LONG_MAX > 4000000000 if (my_png.Width > LONG_MAX || my_png.Height > LONG_MAX) { my_png.Width >>= 32; my_png.Height >>= 32; }