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 memcpy(buf, png_ptr->jmpbuf, sizeof(jmp_buf)); 00070 longjmp(buf, 1); 00071 } 00072 00073 00074 PNGImageLoader::PNGImageLoader() 00075 : ImageLoader("PNG Image Loader based on libpng") 00076 { 00077 } 00078 PNGImageLoader::~PNGImageLoader() 00079 { 00080 } 00081 00082 00083 ImageContext* PNGImageLoader::loadHeader(PixelFormat& formatSource, DataSource* data) 00084 { 00085 PNGImageContext* png = new PNGImageContext(data); 00086 if (!png) 00087 { 00088 return 0; 00089 00090 } 00091 // Prepare png loading 00092 png->d_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); 00093 if (png->d_png_ptr == 0) 00094 { 00095 delete png; 00096 return 0; 00097 } 00098 png->d_info_ptr = png_create_info_struct(png->d_png_ptr); 00099 if (png->d_info_ptr == 0) 00100 { 00101 delete png; 00102 return 0; 00103 } 00104 if (setjmp(png_jmpbuf(png->d_png_ptr))) 00105 { 00106 delete png; 00107 return 0; 00108 } 00109 png_set_error_fn(png->d_png_ptr, 0, PNG_error_function, PNG_warning_function); 00110 png_set_read_fn(png->d_png_ptr, png, PNG_read_function); 00111 //png_set_sig_bytes(png->d_png_ptr, 8); 00112 00113 00114 00115 // Read header Check whether PNG can depaletize transparently or not 00116 int png_transform = PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND; 00117 //printf("Start reading png\n"); 00118 png_read_png(png->d_png_ptr, png->d_info_ptr, png_transform, 0); 00119 png->setImageSize(); 00120 png->d_bit_depth = png_get_bit_depth(png->d_png_ptr, png->d_info_ptr); 00121 png->d_num_channels = png_get_channels(png->d_png_ptr, png->d_info_ptr); 00122 //printf("PNG Info: width: %d height: %d bpp: %d channels: %d\n", png->getWidth(), png->getHeight(), png->d_bit_depth, png->d_num_channels); 00123 if (png->d_bit_depth == 8) 00124 { 00125 if (png->d_num_channels == 4) 00126 { 00127 formatSource = PF_RGBA; 00128 } 00129 else if (png->d_num_channels == 3) 00130 { 00131 formatSource = PF_RGB; 00132 } 00133 else 00134 { 00135 delete png; 00136 return 0; 00137 } 00138 } 00139 // Paletized or grayscale not yet handled 00140 else 00141 { 00142 delete png; 00143 return 0; 00144 } 00145 return png; 00146 } 00147 00148 00149 bool PNGImageLoader::loadImageData(PixelOrigin origin, 00150 DataSource* data, 00151 ImageContext* context) 00152 { 00153 PNGImageContext* png = static_cast<PNGImageContext*>(context); 00154 byte red; 00155 byte green; 00156 byte blue; 00157 byte alpha; 00158 size_t width = png->getWidth(); 00159 size_t height = png->getHeight(); 00160 png_bytepp row_pointers = png_get_rows(png->d_png_ptr, png->d_info_ptr); 00161 if (png->d_bit_depth == 8) 00162 { 00163 // Read RGBA 00164 if (png->d_num_channels == 4) 00165 { 00166 for (size_t j = 0 ; j < height ; ++j) 00167 { 00168 for(size_t i = 0 ; i < width ; ++i) 00169 { 00170 size_t pixel_offset = 4 * i; 00171 red = *(row_pointers[j] + pixel_offset); 00172 green = *(row_pointers[j] + pixel_offset + 1); 00173 blue = *(row_pointers[j] + pixel_offset + 2); 00174 alpha = *(row_pointers[j] + pixel_offset + 3); 00175 png->setNextPixel(red, green, blue, alpha); 00176 } 00177 } 00178 } 00179 else if (png->d_num_channels == 3) 00180 { 00181 alpha = 0xff; 00182 for (size_t j = 0 ; j < height ; ++j) 00183 { 00184 for(size_t i = 0 ; i < width ; ++i) 00185 { 00186 size_t pixel_offset = 3 * i; 00187 red = *(row_pointers[j] + pixel_offset); 00188 green = *(row_pointers[j] + pixel_offset + 1); 00189 blue = *(row_pointers[j] + pixel_offset + 2); 00190 png->setNextPixel(red, green, blue, alpha); 00191 } 00192 } 00193 00194 } 00195 } 00196 if (origin == PO_BOTTOM_LEFT) 00197 return png->flipVertically(); 00198 00199 return true; 00200 } 00201 00202 } // End section of namespace SILLY