TexturePNG.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2006  The Pentagram Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "pent_include.h"
00020 #include "TexturePNG.h"
00021 
00022 #include "IDataSource.h"
00023 
00024 // CHECKME: how should we include png.h ? (And how should we check for it?)
00025 #include <png.h>
00026 
00027 
00028 static void idatasource_png_read_data(png_structp png_ptr,
00029                                                                           png_bytep data, png_size_t length)
00030 {
00031         voidp read_io_ptr = png_get_io_ptr(png_ptr);
00032         IDataSource* ds = reinterpret_cast<IDataSource*>(read_io_ptr);
00033         ds->read(data, length);
00034 }
00035 
00036 bool TexturePNG::Read(IDataSource *ds)
00037 {
00038         png_bytep* row_pointers = 0;
00039 
00040         png_byte header[8];
00041         if (ds->read(header, 8) < 8) return false;
00042         if (png_sig_cmp(header, 0, 8)) {
00043                 return false;
00044         }
00045         png_structp png_ptr = png_create_read_struct(
00046                 PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00047         if (!png_ptr)
00048                 return false;
00049 
00050         png_infop info_ptr = png_create_info_struct(png_ptr);
00051         if (!info_ptr)
00052         {
00053                 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
00054                 return false;
00055         }
00056 
00057         png_infop end_info = png_create_info_struct(png_ptr);
00058         if (!end_info)
00059         {
00060                 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00061                 return false;
00062         }
00063 
00064         if (setjmp(png_jmpbuf(png_ptr))) {
00065                 delete[] row_pointers;
00066                 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00067                 return false;
00068         }
00069 
00070         png_set_read_fn(png_ptr, ds, idatasource_png_read_data);
00071         png_set_sig_bytes(png_ptr, 8);
00072 
00073         png_read_info(png_ptr, info_ptr);
00074 
00075         png_uint_32 width, height;
00076         int bit_depth, color_type;
00077         int interlace_type, compression_type, filter_method;
00078         png_get_IHDR(png_ptr, info_ptr, &width, &height,
00079                                  &bit_depth, &color_type,
00080                                  &interlace_type, &compression_type, &filter_method);
00081 
00082         if (color_type == PNG_COLOR_TYPE_PALETTE)
00083                 png_set_palette_to_rgb(png_ptr);
00084 
00085         if (color_type == PNG_COLOR_TYPE_GRAY || 
00086                 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00087                 png_set_gray_to_rgb(png_ptr);
00088 
00089         if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00090                 png_set_tRNS_to_alpha(png_ptr);
00091 
00092         if (bit_depth == 16)
00093                 png_set_strip_16(png_ptr);
00094 
00095         if (color_type == PNG_COLOR_TYPE_RGB)
00096                 png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
00097 
00098         png_read_update_info(png_ptr, info_ptr);
00099 
00100         png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
00101         if (rowbytes != width * 4) {
00102                 perr << "TexturePNG::Read(): failed to convert PNG to 32 bit RGBA"
00103                          << std::endl;
00104                 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00105                 return false;
00106         }
00107 
00108         buffer = new uint32[width*height];
00109         if (!buffer) {
00110                 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00111                 return false;      
00112         }
00113 
00114         row_pointers = new png_bytep[height];
00115         for (unsigned int i = 0; i < height; ++i) {
00116                 row_pointers[i] = reinterpret_cast<png_bytep>(&buffer[i*width]);
00117         }
00118 
00119         png_read_image(png_ptr, row_pointers);
00120 
00121         delete[] row_pointers;
00122         row_pointers = 0;
00123 
00124         // the end_info struct isn't used, but passing it anyway for now
00125         png_read_end(png_ptr, end_info);
00126 
00127         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00128 
00129         this->width = width;
00130         this->height = height;
00131         this->format = TEX_FMT_STANDARD;
00132         this->wlog2 = -1;
00133         this->hlog2 = -1;
00134 
00135         // Repack RGBA
00136         for (unsigned int i = 0; i < height * width; ++i) {
00137                 png_bytep p = reinterpret_cast<png_bytep>(&buffer[i]);
00138                 buffer[i] =(p[0] << TEX32_R_SHIFT) 
00139                         | (p[1] << TEX32_G_SHIFT)
00140                         | (p[2] << TEX32_B_SHIFT)
00141                         | (p[3] << TEX32_A_SHIFT);
00142         }
00143         
00144         return true;
00145 }

Generated on Fri Jul 27 22:27:42 2007 for pentagram by  doxygen 1.4.7