X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=plugins%2Fimagepng%2Fplugin.cpp;h=e358312716a7b80e7cde6133748762e0665d0ccc;hp=eb9b9605c6e6cea239a82b9e0360483d6cba1e8e;hb=33efc9089296fc4e5f54d43581a0db81576ba848;hpb=80378101101ca1762bbf5638a9e3566893096d8a;ds=sidebyside diff --git a/plugins/imagepng/plugin.cpp b/plugins/imagepng/plugin.cpp index eb9b9605..e3583127 100644 --- a/plugins/imagepng/plugin.cpp +++ b/plugins/imagepng/plugin.cpp @@ -1,242 +1,247 @@ -/* -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. - -This file is part of GtkRadiant. - -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -// ============================================================================= -// global tables - -#include "plugin.h" - -_QERFuncTable_1 g_FuncTable; -_QERFileSystemTable g_FileSystemTable; - -// ============================================================================= -// SYNAPSE - -#include "synapse.h" - -class CSynapseClientImage : public CSynapseClient -{ -public: - // CSynapseClient API - bool RequestAPI(APIDescriptor_t *pAPI); - const char* GetInfo(); - - CSynapseClientImage() { } - virtual ~CSynapseClientImage() { } -}; - -CSynapseServer* g_pSynapseServer = NULL; -CSynapseClientImage g_SynapseClient; - -extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces (const char *version, CSynapseServer *pServer) -{ - if (strcmp(version, SYNAPSE_VERSION)) - { - Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version); - return NULL; - } - g_pSynapseServer = pServer; - g_pSynapseServer->IncRef(); - Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); - - g_SynapseClient.AddAPI(IMAGE_MAJOR, "png", sizeof(_QERPlugImageTable)); - g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1), SYN_REQUIRE, &g_FuncTable); - // NOTE: if imagepng starts being used for non "VFS" "pk3" config, need to add a dynamic config chunk - // see: - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=794 - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=800 - g_SynapseClient.AddAPI(VFS_MAJOR, "pk3", sizeof(_QERFileSystemTable), SYN_REQUIRE, &g_FileSystemTable); - - return &g_SynapseClient; -} - -bool CSynapseClientImage::RequestAPI(APIDescriptor_t *pAPI) -{ - if (!strcmp(pAPI->major_name, IMAGE_MAJOR)) - { - _QERPlugImageTable* pTable= static_cast<_QERPlugImageTable*>(pAPI->mpTable); - if (!strcmp(pAPI->minor_name, "png")) - { - pTable->m_pfnLoadImage = &LoadImage; - return true; - } - } - - Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); - return false; -} - -#include "version.h" - -const char* CSynapseClientImage::GetInfo() -{ - return "PNG loader module built " __DATE__ " " RADIANT_VERSION; -} - - - -// ====== PNG loader functionality ====== - -#include "png.h" - -#ifdef __APPLE__ //tigital -#include -#endif - -void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) -{ - g_FuncTable.m_pfnSysPrintf ("libpng warning: %s\n", warning_msg); -} - -void user_error_fn(png_structp png_ptr, png_const_charp error_msg) -{ - g_FuncTable.m_pfnSysPrintf ("libpng error: %s\n", error_msg); - longjmp(png_ptr->jmpbuf, 0); -} - -void user_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) -{ - png_bytep *p_p_fbuffer = (png_bytep*)png_get_io_ptr(png_ptr); - memcpy(data, *p_p_fbuffer, length); - *p_p_fbuffer += length; -} - -void LoadImage (const char *filename, unsigned char **pic, int *width, int *height) -{ - png_byte** row_pointers; - unsigned char *fbuffer = NULL; - png_bytep p_fbuffer; - - int nLen = g_FileSystemTable.m_pfnLoadFile( (char *)filename, (void **)&fbuffer, 0 ); - if (nLen == -1) - return; - - p_fbuffer = fbuffer; - - // the reading glue - // http://www.libpng.org/pub/png/libpng-manual.html - - png_structp png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, png_voidp_NULL, - user_error_fn, user_warning_fn); - if (!png_ptr) - { - g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_read_struct\n"); - return; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, - png_infopp_NULL, png_infopp_NULL); - g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (info_ptr)\n"); - return; - } - - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) { - png_destroy_read_struct(&png_ptr, &info_ptr, - png_infopp_NULL); - g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (end_info)\n"); - return; - } - - // configure the read function - png_set_read_fn(png_ptr, (voidp)&p_fbuffer, (png_rw_ptr)&user_read_data); - - if (setjmp(png_ptr->jmpbuf)) { - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - if (*pic) - { - g_free(*pic); - free(row_pointers); - } - return; - } - - png_read_info(png_ptr, info_ptr); - - int bit_depth = png_get_bit_depth(png_ptr, info_ptr); - int color_type = png_get_color_type(png_ptr, info_ptr); - - // we want to treat all images the same way - // The following code transforms grayscale images of less than 8 to 8 bits, - // changes paletted images to RGB, and adds a full alpha channel if there is - // transparency information in a tRNS chunk. - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_gray_1_2_4_to_8(png_ptr); - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png_ptr); - - if ( ! ( color_type & PNG_COLOR_MASK_ALPHA ) ) { - // Set the background color to draw transparent and alpha images over. - png_color_16 my_background, *image_background; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) - png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - else - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - - // Add alpha byte after each RGB triplet - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - } - - // read the sucker in one chunk - png_read_update_info(png_ptr, info_ptr); - - color_type = png_get_color_type(png_ptr, info_ptr); - bit_depth = png_get_bit_depth(png_ptr, info_ptr); - - *width = png_get_image_width(png_ptr, info_ptr); - *height = png_get_image_height(png_ptr, info_ptr); - - // allocate the pixel buffer, and the row pointers - int size = (*width)*(*height)*4; - // still have to use that g_malloc heresy - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491 - *pic = (unsigned char *)g_malloc(size); - row_pointers = (png_byte**) malloc((*height) * sizeof(png_byte*)); - - int i; - for(i = 0; i < (*height); i++) - row_pointers[i] = (png_byte*)(*pic) + i * 4 * (*width); - - // actual read - png_read_image(png_ptr, row_pointers); - - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end(png_ptr, info_ptr); - - /* free up the memory structure */ - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - - free(row_pointers); - g_FileSystemTable.m_pfnFreeFile (fbuffer); -} - - +/* +Copyright (C) 1999-2007 id Software, Inc. and contributors. +For a list of contributors, see the accompanying CONTRIBUTORS file. + +This file is part of GtkRadiant. + +GtkRadiant is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +GtkRadiant is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GtkRadiant; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +// ============================================================================= +// global tables + +#include "plugin.h" + +_QERFuncTable_1 g_FuncTable; +_QERFileSystemTable g_FileSystemTable; + +// ============================================================================= +// SYNAPSE + +#include "synapse.h" + +class CSynapseClientImage : public CSynapseClient +{ +public: + // CSynapseClient API + bool RequestAPI(APIDescriptor_t *pAPI); + const char* GetInfo(); + + CSynapseClientImage() { } + virtual ~CSynapseClientImage() { } +}; + +CSynapseServer* g_pSynapseServer = NULL; +CSynapseClientImage g_SynapseClient; + +#if __GNUC__ >= 4 +#pragma GCC visibility push(default) +#endif +extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) { +#if __GNUC__ >= 4 +#pragma GCC visibility pop +#endif + if (strcmp(version, SYNAPSE_VERSION)) + { + Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version); + return NULL; + } + g_pSynapseServer = pServer; + g_pSynapseServer->IncRef(); + Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); + + g_SynapseClient.AddAPI(IMAGE_MAJOR, "png", sizeof(_QERPlugImageTable)); + g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1), SYN_REQUIRE, &g_FuncTable); + // NOTE: if imagepng starts being used for non "VFS" "pk3" config, need to add a dynamic config chunk + // see: + // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=794 + // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=800 + g_SynapseClient.AddAPI(VFS_MAJOR, "pk3", sizeof(_QERFileSystemTable), SYN_REQUIRE, &g_FileSystemTable); + + return &g_SynapseClient; +} + +bool CSynapseClientImage::RequestAPI(APIDescriptor_t *pAPI) +{ + if (!strcmp(pAPI->major_name, IMAGE_MAJOR)) + { + _QERPlugImageTable* pTable= static_cast<_QERPlugImageTable*>(pAPI->mpTable); + if (!strcmp(pAPI->minor_name, "png")) + { + pTable->m_pfnLoadImage = &LoadImage; + return true; + } + } + + Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); + return false; +} + +#include "version.h" + +const char* CSynapseClientImage::GetInfo() +{ + return "PNG loader module built " __DATE__ " " RADIANT_VERSION; +} + + + +// ====== PNG loader functionality ====== + +#include "png.h" + +#ifdef __APPLE__ //tigital +#include +#endif + +void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) +{ + g_FuncTable.m_pfnSysPrintf ("libpng warning: %s\n", warning_msg); +} + +void user_error_fn(png_structp png_ptr, png_const_charp error_msg) +{ + g_FuncTable.m_pfnSysPrintf ("libpng error: %s\n", error_msg); + longjmp(png_ptr->jmpbuf, 0); +} + +void user_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) +{ + png_bytep *p_p_fbuffer = (png_bytep*)png_get_io_ptr(png_ptr); + memcpy(data, *p_p_fbuffer, length); + *p_p_fbuffer += length; +} + +void LoadImage (const char *filename, unsigned char **pic, int *width, int *height) +{ + png_byte** row_pointers; + unsigned char *fbuffer = NULL; + png_bytep p_fbuffer; + + int nLen = g_FileSystemTable.m_pfnLoadFile( (char *)filename, (void **)&fbuffer, 0 ); + if (nLen == -1) + return; + + p_fbuffer = fbuffer; + + // the reading glue + // http://www.libpng.org/pub/png/libpng-manual.html + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, png_voidp_NULL, + user_error_fn, user_warning_fn); + if (!png_ptr) + { + g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_read_struct\n"); + return; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, + png_infopp_NULL, png_infopp_NULL); + g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (info_ptr)\n"); + return; + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + png_destroy_read_struct(&png_ptr, &info_ptr, + png_infopp_NULL); + g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (end_info)\n"); + return; + } + + // configure the read function + png_set_read_fn(png_ptr, (voidp)&p_fbuffer, (png_rw_ptr)&user_read_data); + + if (setjmp(png_ptr->jmpbuf)) { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + if (*pic) + { + g_free(*pic); + free(row_pointers); + } + return; + } + + png_read_info(png_ptr, info_ptr); + + int bit_depth = png_get_bit_depth(png_ptr, info_ptr); + int color_type = png_get_color_type(png_ptr, info_ptr); + + // we want to treat all images the same way + // The following code transforms grayscale images of less than 8 to 8 bits, + // changes paletted images to RGB, and adds a full alpha channel if there is + // transparency information in a tRNS chunk. + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_gray_1_2_4_to_8(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + + if ( ! ( color_type & PNG_COLOR_MASK_ALPHA ) ) { + // Set the background color to draw transparent and alpha images over. + png_color_16 my_background, *image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + + // Add alpha byte after each RGB triplet + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + } + + // read the sucker in one chunk + png_read_update_info(png_ptr, info_ptr); + + color_type = png_get_color_type(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + *width = png_get_image_width(png_ptr, info_ptr); + *height = png_get_image_height(png_ptr, info_ptr); + + // allocate the pixel buffer, and the row pointers + int size = (*width)*(*height)*4; + // still have to use that g_malloc heresy + // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491 + *pic = (unsigned char *)g_malloc(size); + row_pointers = (png_byte**) malloc((*height) * sizeof(png_byte*)); + + int i; + for(i = 0; i < (*height); i++) + row_pointers[i] = (png_byte*)(*pic) + i * 4 * (*width); + + // actual read + png_read_image(png_ptr, row_pointers); + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + /* free up the memory structure */ + png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + free(row_pointers); + g_FileSystemTable.m_pfnFreeFile (fbuffer); +} + +