00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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