Simple Image Loading LibrarY
0.1.0
|
00001 /*********************************************************************** 00002 filename: SILLYPNGImageLoader.cpp 00003 created: 11 Jun 2006 00004 author: Olivier Delannoy 00005 00006 purpose: Definition of the PNGImageLoader methods 00007 *************************************************************************/ 00008 /*************************************************************************** 00009 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team 00010 * 00011 * Permission is hereby granted, free of charge, to any person obtaining 00012 * a copy of this software and associated documentation files (the 00013 * "Software"), to deal in the Software without restriction, including 00014 * without limitation the rights to use, copy, modify, merge, publish, 00015 * distribute, sublicense, and/or sell copies of the Software, and to 00016 * permit persons to whom the Software is furnished to do so, subject to 00017 * the following conditions: 00018 * 00019 * The above copyright notice and this permission notice shall be 00020 * included in all copies or substantial portions of the Software. 00021 * 00022 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00023 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00024 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00025 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 00026 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00027 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00028 * OTHER DEALINGS IN THE SOFTWARE. 00029 ***************************************************************************/ 00030 #ifdef HAVE_CONFIG_H 00031 #include <config.h> 00032 #endif 00033 00034 #include "loaders/SILLYPNGImageLoader.h" 00035 00036 #ifndef SILLY_OPT_INLINE 00037 #define inline 00038 #include "loaders/SILLYPNGImageLoader.icpp" 00039 #undef inline 00040 #endif 00041 00042 #include "loaders/SILLYPNGImageContext.h" 00043 #include <png.h> 00044 // Start section of namespace SILLY 00045 namespace SILLY 00046 { 00047 void PNG_read_function(png_structp png_ptr, png_bytep data, png_size_t length) 00048 { 00049 PNGImageContext* png = reinterpret_cast<PNGImageContext*>(png_get_io_ptr(png_ptr)); 00050 int readed = png->read(data, length); 00051 if (readed != (int)length) 00052 { 00053 png_error(png_ptr, "PNG_read_function error"); 00054 } 00055 } 00056 00057 void PNG_warning_function(png_structp png_ptr, 00058 png_const_charp error) 00059 { 00060 // printf("PNG Warning: %s\n", error); 00061 } 00062 00063 void PNG_error_function(png_structp png_ptr, 00064 png_const_charp error) 00065 { 00066 // printf("PNG Error: %s\n", error); 00067 // copied from libpng's pngerror.cpp 00068 jmp_buf buf; 00069 #if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 4 00070 memcpy(buf, png_jmpbuf((png_ptr)), sizeof(jmp_buf)); 00071 #else 00072 memcpy(buf, png_ptr->jmpbuf, sizeof(jmp_buf)); 00073 #endif 00074 longjmp(buf, 1); 00075 } 00076 00077 00078 PNGImageLoader::PNGImageLoader() 00079 : ImageLoader("PNG Image Loader based on libpng") 00080 { 00081 } 00082 PNGImageLoader::~PNGImageLoader() 00083 { 00084 } 00085 00086 00087 ImageContext* PNGImageLoader::loadHeader(PixelFormat& formatSource, DataSource* data) 00088 { 00089 PNGImageContext* png = new PNGImageContext(data); 00090 if (!png) 00091 { 00092 return 0; 00093 00094 } 00095 // Prepare png loading 00096 png->d_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); 00097 if (png->d_png_ptr == 0) 00098 { 00099 delete png; 00100 return 0; 00101 } 00102 png->d_info_ptr = png_create_info_struct(png->d_png_ptr); 00103 if (png->d_info_ptr == 0) 00104 { 00105 delete png; 00106 return 0; 00107 } 00108 if (setjmp(png_jmpbuf(png->d_png_ptr))) 00109 { 00110 delete png; 00111 return 0; 00112 } 00113 png_set_error_fn(png->d_png_ptr, 0, PNG_error_function, PNG_warning_function); 00114 png_set_read_fn(png->d_png_ptr, png, PNG_read_function); 00115 //png_set_sig_bytes(png->d_png_ptr, 8); 00116 00117 00118 00119 // Read header Check whether PNG can depaletize transparently or not 00120 int png_transform = PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND; 00121 //printf("Start reading png\n"); 00122 png_read_png(png->d_png_ptr, png->d_info_ptr, png_transform, 0); 00123 png->setImageSize(); 00124 png->d_bit_depth = png_get_bit_depth(png->d_png_ptr, png->d_info_ptr); 00125 png->d_num_channels = png_get_channels(png->d_png_ptr, png->d_info_ptr); 00126 //printf("PNG Info: width: %d height: %d bpp: %d channels: %d\n", png->getWidth(), png->getHeight(), png->d_bit_depth, png->d_num_channels); 00127 if (png->d_bit_depth == 8) 00128 { 00129 if (png->d_num_channels == 4) 00130 { 00131 formatSource = PF_RGBA; 00132 } 00133 else if (png->d_num_channels == 3) 00134 { 00135 formatSource = PF_RGB; 00136 } 00137 else 00138 { 00139 delete png; 00140 return 0; 00141 } 00142 } 00143 // Paletized or grayscale not yet handled 00144 else 00145 { 00146 delete png; 00147 return 0; 00148 } 00149 return png; 00150 } 00151 00152 00153 bool PNGImageLoader::loadImageData(PixelOrigin origin, 00154 DataSource* data, 00155 ImageContext* context) 00156 { 00157 PNGImageContext* png = static_cast<PNGImageContext*>(context); 00158 byte red; 00159 byte green; 00160 byte blue; 00161 byte alpha; 00162 size_t width = png->getWidth(); 00163 size_t height = png->getHeight(); 00164 png_bytepp row_pointers = png_get_rows(png->d_png_ptr, png->d_info_ptr); 00165 if (png->d_bit_depth == 8) 00166 { 00167 // Read RGBA 00168 if (png->d_num_channels == 4) 00169 { 00170 for (size_t j = 0 ; j < height ; ++j) 00171 { 00172 for(size_t i = 0 ; i < width ; ++i) 00173 { 00174 size_t pixel_offset = 4 * i; 00175 red = *(row_pointers[j] + pixel_offset); 00176 green = *(row_pointers[j] + pixel_offset + 1); 00177 blue = *(row_pointers[j] + pixel_offset + 2); 00178 alpha = *(row_pointers[j] + pixel_offset + 3); 00179 png->setNextPixel(red, green, blue, alpha); 00180 } 00181 } 00182 } 00183 else if (png->d_num_channels == 3) 00184 { 00185 alpha = 0xff; 00186 for (size_t j = 0 ; j < height ; ++j) 00187 { 00188 for(size_t i = 0 ; i < width ; ++i) 00189 { 00190 size_t pixel_offset = 3 * i; 00191 red = *(row_pointers[j] + pixel_offset); 00192 green = *(row_pointers[j] + pixel_offset + 1); 00193 blue = *(row_pointers[j] + pixel_offset + 2); 00194 png->setNextPixel(red, green, blue, alpha); 00195 } 00196 } 00197 00198 } 00199 } 00200 if (origin == PO_BOTTOM_LEFT) 00201 return png->flipVertically(); 00202 00203 return true; 00204 } 00205 00206 } // End section of namespace SILLY