D:/Projects/CEGUI/Silly/src/loaders/SILLYPNGImageLoader.cpp

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 

Generated on Sun Apr 6 14:47:06 2008 for Simple Image Loading LibrarY by  doxygen 1.5.2