PNGLoader.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2005 Dave Griffiths
00002 //
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 
00017 #include <png.h>
00018 #include "PNGLoader.h"
00019 #include "Trace.h"
00020 
00021 using namespace Fluxus;
00022 
00023 unsigned char *PNGLoader::Load(const string &Filename, unsigned int &w, unsigned int &h, PixelFormat &pf)
00024 {
00025     unsigned char *ImageData = NULL;
00026     FILE *fp=fopen(Filename.c_str(),"rb");
00027     if (!fp || Filename=="") 
00028     {
00029         Trace::Stream<<"Couldn't open image ["<<Filename<<"]"<<endl;
00030     }
00031     else
00032     {
00033         png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00034         png_infop info_ptr = png_create_info_struct(png_ptr);
00035             
00036         if (setjmp(png_jmpbuf(png_ptr))) 
00037         {
00038             png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
00039             Trace::Stream<<"Error reading image ["<<Filename<<"]"<<endl;
00040             return NULL;
00041         }
00042         
00043         png_init_io(png_ptr, fp);
00044         png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);      
00045         fclose(fp);
00046         
00047         ImageData = new unsigned char[png_ptr->rowbytes*png_ptr->height];
00048         int p=0;
00049         for (unsigned int row = 0; row < png_ptr->height; row++)
00050         {
00051             for (unsigned int i=0; i<png_ptr->rowbytes; i++)
00052             {
00053                 ImageData[p]=(unsigned char)info_ptr->row_pointers[row][i];
00054                 p++;
00055             }
00056         }
00057         
00058         w=png_ptr->width;
00059         h=png_ptr->height;
00060         
00061         switch (png_ptr->color_type)
00062         {
00063             case PNG_COLOR_TYPE_RGB : pf=RGB; break;
00064             case PNG_COLOR_TYPE_RGB_ALPHA : pf=RGBA; break;
00065             default : Trace::Stream<<"PNG pixel format not supported : "<<png_ptr->color_type<<endl;
00066         }
00067 
00068         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); 
00069     }
00070     
00071     return ImageData;
00072 }
00073 
00074 void PNGLoader::Save(const string &Filename, unsigned int w, unsigned int h, PixelFormat pf, unsigned char *data)
00075 {
00076     FILE *f;
00077     png_structp ppng;
00078     png_infop pinfo;
00079     png_text atext[3];
00080     unsigned int i;
00081 
00082     unsigned int numchannels = 3;
00083     if (pf==RGBA) numchannels = 4;
00084 
00085     if (!(f = fopen (Filename.c_str(), "wb")))
00086     {
00087         Trace::Stream<<"Error writing png file"<<endl;
00088         return;
00089     }
00090 
00091     if (!(ppng = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
00092     {
00093         Trace::Stream<<"Error writing png file"<<endl;
00094         fclose (f);
00095         return;
00096     }
00097 
00098     if (!(pinfo = png_create_info_struct (ppng)))
00099     {
00100         Trace::Stream<<"Error writing png file"<<endl;
00101         fclose (f);
00102         png_destroy_write_struct (&ppng, NULL);
00103         return;
00104     }
00105 
00106     if (setjmp (png_jmpbuf (ppng)))
00107     {
00108         Trace::Stream<<"Error writing png file"<<endl;
00109         fclose (f);
00110         png_destroy_write_struct (&ppng, &pinfo);
00111         return;
00112     }
00113 
00114     png_init_io (ppng, f);
00115 
00116     if (pf==RGB)
00117     {
00118         png_set_IHDR (ppng, pinfo, w, h, 8, PNG_COLOR_TYPE_RGB,
00119         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
00120         PNG_FILTER_TYPE_BASE);
00121     }
00122     else if (pf==RGBA)
00123     {
00124         png_set_IHDR (ppng, pinfo, w, h, 8, PNG_COLOR_TYPE_RGBA,
00125         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
00126         PNG_FILTER_TYPE_BASE);
00127     }
00128     else
00129     {
00130         Trace::Stream<<"Error, unknown pixel format"<<endl;
00131         fclose (f);
00132         png_destroy_write_struct (&ppng, NULL);
00133         return;     
00134     }
00135 
00136     atext[0].key = "title";
00137     atext[0].text = "made with fluxus";
00138     atext[0].compression = PNG_TEXT_COMPRESSION_NONE;
00139     #ifdef PNG_iTXt_SUPPORTED
00140     text_ptr[0].lang = NULL;
00141     text_ptr[1].lang = NULL;
00142     #endif
00143     png_set_text (ppng, pinfo, atext, 2);
00144     png_write_info (ppng, pinfo);
00145     unsigned int stride=w*numchannels;
00146     {
00147         png_bytep *aprow = (png_bytep*) malloc(h * sizeof(png_bytep));
00148         for (i = 0; i < h; ++i) aprow[i] = data + stride * i;
00149         png_write_image (ppng, aprow);
00150         free(aprow);
00151     }
00152 
00153     png_write_end (ppng, pinfo);
00154     png_destroy_write_struct (&ppng, &pinfo);
00155     fclose (f);
00156 }
00157 

Generated on Wed Sep 17 21:16:30 2008 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1