1 /*! ========================================================================
4 ** $Id: mptr_png.cpp,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
8 ** This software and associated documentation
9 ** are CONFIDENTIAL and PROPRIETARY property of
10 ** the above-mentioned copyright holder.
12 ** You may not copy, print, publish, or in any
13 ** other way distribute this software without
14 ** a prior written agreement with
15 ** the copyright holder.
17 ** === N O T E S ===========================================================
19 ** ========================================================================= */
22 ** \todo Support 16 bit PNG files
23 ** \todo Support GAMMA correction
24 ** \todo Fix memory leaks
27 /* === H E A D E R S ======================================================= */
37 #include <sinfg/importer.h>
38 #include <sinfg/time.h>
39 #include <sinfg/general.h>
47 /* === M A C R O S ========================================================= */
49 using namespace sinfg;
53 #define PNG_CHECK_BYTES 8
55 /* === G L O B A L S ======================================================= */
57 SINFG_IMPORTER_INIT(png_mptr);
58 SINFG_IMPORTER_SET_NAME(png_mptr,"png_mptr");
59 SINFG_IMPORTER_SET_EXT(png_mptr,"png");
60 SINFG_IMPORTER_SET_VERSION(png_mptr,"0.1");
61 SINFG_IMPORTER_SET_CVS_ID(png_mptr,"$Id: mptr_png.cpp,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $");
63 /* === M E T H O D S ======================================================= */
66 png_mptr::png_out_error(png_struct *png_data,const char *msg)
68 //png_mptr *me=(png_mptr*)png_data->error_ptr;
69 sinfg::error(strprintf("png_mptr: error: %s",msg));
74 png_mptr::png_out_warning(png_struct *png_data,const char *msg)
76 //png_mptr *me=(png_mptr*)png_data->error_ptr;
77 sinfg::warning(strprintf("png_mptr: warning: %s",msg));
82 png_mptr::read_chunk_callback(png_struct *png_data, png_unknown_chunkp chunk)
84 /* The unknown chunk structure contains your
89 /* Note that libpng has already taken care of
92 /* put your code here. Return one of the
95 //return (-n); /* chunk had an error */
96 return (0); /* did not recognize */
97 //return (n); /* success */
100 png_mptr::png_mptr(const char *file_name)
104 /* Open the file pointer */
105 FILE *file = fopen(file_name, "rb");
108 //! \todo THROW SOMETHING
109 throw strprintf("Unable to physically open %s",file_name);
114 /* Make sure we are dealing with a PNG format file */
115 png_byte header[PNG_CHECK_BYTES];
116 fread(header, 1, PNG_CHECK_BYTES, file);
117 bool is_png = !png_sig_cmp(header, 0, PNG_CHECK_BYTES);
120 //! \todo THROW SOMETHING
121 throw strprintf("This (\"%s\") doesn't appear to be a PNG file",file_name);
126 png_structp png_ptr = png_create_read_struct
127 (PNG_LIBPNG_VER_STRING, (png_voidp)this,
128 &png_mptr::png_out_error, &png_mptr::png_out_warning);
131 //! \todo THROW SOMETHING
132 throw String("error on importer construction, *WRITEME*3");
136 png_infop info_ptr = png_create_info_struct(png_ptr);
139 png_destroy_read_struct(&png_ptr,
140 (png_infopp)NULL, (png_infopp)NULL);
141 //! \todo THROW SOMETHING
142 throw String("error on importer construction, *WRITEME*4");
146 png_infop end_info = png_create_info_struct(png_ptr);
149 png_destroy_read_struct(&png_ptr, &info_ptr,
151 //! \todo THROW SOMETHING
152 throw String("error on importer construction, *WRITEME*4");
158 png_init_io(png_ptr, file);
159 png_set_sig_bytes(png_ptr,PNG_CHECK_BYTES);
162 if (png_get_gAMA(png_ptr, info_ptr, &fgamma))
164 sinfg::info("PNG: Image gamma is %f",fgamma);
165 png_set_gamma(png_ptr, gamma().get_gamma(), fgamma);
170 if (setjmp(png_jmpbuf(png_ptr)))
172 sinfg::error("Unable to setup longjump");
173 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
175 //! \todo THROW SOMETHING
176 throw String("error on importer construction, *WRITEME*5");
181 png_set_read_user_chunk_fn(png_ptr, this, &png_mptr::read_chunk_callback);
184 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING|PNG_TRANSFORM_STRIP_16, NULL);
186 int bit_depth,color_type,interlace_type, compression_type,filter_method;
187 png_uint_32 width,height;
189 png_get_IHDR(png_ptr, info_ptr, &width, &height,
190 &bit_depth, &color_type, &interlace_type,
191 &compression_type, &filter_method);
193 png_bytep *row_pointers=new png_bytep[height];
194 row_pointers = png_get_rows(png_ptr, info_ptr);
197 surface_buffer.set_wh(width,height);
201 case PNG_COLOR_TYPE_RGB:
203 for(y=0;y<surface_buffer.get_h();y++)
204 for(x=0;x<surface_buffer.get_w();x++)
206 float r=gamma().r_U8_to_F32((unsigned char)row_pointers[y][x*3+0]);
207 float g=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x*3+1]);
208 float b=gamma().b_U8_to_F32((unsigned char)row_pointers[y][x*3+2]);
209 surface_buffer[y][x]=Color(
216 surface_buffer[y][x]=Color(
217 (float)(unsigned char)row_pointers[y][x*3+0]*(1.0/255.0),
218 (float)(unsigned char)row_pointers[y][x*3+1]*(1.0/255.0),
219 (float)(unsigned char)row_pointers[y][x*3+2]*(1.0/255.0),
226 case PNG_COLOR_TYPE_RGB_ALPHA:
228 for(y=0;y<surface_buffer.get_h();y++)
229 for(x=0;x<surface_buffer.get_w();x++)
231 float r=gamma().r_U8_to_F32((unsigned char)row_pointers[y][x*4+0]);
232 float g=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x*4+1]);
233 float b=gamma().b_U8_to_F32((unsigned char)row_pointers[y][x*4+2]);
234 surface_buffer[y][x]=Color(
238 (float)(unsigned char)row_pointers[y][x*4+3]*(1.0/255.0)
241 surface_buffer[y][x]=Color(
242 (float)(unsigned char)row_pointers[y][x*4+0]*(1.0/255.0),
243 (float)(unsigned char)row_pointers[y][x*4+1]*(1.0/255.0),
244 (float)(unsigned char)row_pointers[y][x*4+2]*(1.0/255.0),
245 (float)(unsigned char)row_pointers[y][x*4+3]*(1.0/255.0)
251 case PNG_COLOR_TYPE_GRAY:
252 for(y=0;y<surface_buffer.get_h();y++)
253 for(x=0;x<surface_buffer.get_w();x++)
255 float gray=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x]);
256 //float gray=(float)(unsigned char)row_pointers[y][x]*(1.0/255.0);
257 surface_buffer[y][x]=Color(
266 case PNG_COLOR_TYPE_GRAY_ALPHA:
267 for(y=0;y<surface_buffer.get_h();y++)
268 for(x=0;x<surface_buffer.get_w();x++)
270 float gray=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x*2]);
271 // float gray=(float)(unsigned char)row_pointers[y][x*2]*(1.0/255.0);
272 surface_buffer[y][x]=Color(
276 (float)(unsigned char)row_pointers[y][x*2+1]*(1.0/255.0)
281 case PNG_COLOR_TYPE_PALETTE:
282 sinfg::warning("png_mptr: Paletted PNGs aren't yet fully supported.");
283 for(y=0;y<surface_buffer.get_h();y++)
284 for(x=0;x<surface_buffer.get_w();x++)
286 float r=gamma().r_U8_to_F32((unsigned char)png_ptr->palette[row_pointers[y][x]].red);
287 float g=gamma().g_U8_to_F32((unsigned char)png_ptr->palette[row_pointers[y][x]].green);
288 float b=gamma().b_U8_to_F32((unsigned char)png_ptr->palette[row_pointers[y][x]].blue);
289 surface_buffer[y][x]=Color(
298 sinfg::error("png_mptr: error: Unsupported color type");
299 //! \todo THROW SOMETHING
300 throw String("error on importer construction, *WRITEME*6");
306 // \fixme These shouldn't be uncommented, but for some
307 // reason, they crash the program. I will have to look into this
308 // later. This is a memory leak, but it shouldn't be too bad.
311 png_read_end(png_ptr, end_info);
312 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
316 delete [] row_pointers;
319 png_mptr::~png_mptr()
325 png_mptr::get_frame(sinfg::Surface &surface,Time, sinfg::ProgressCallback *cb)
327 surface.mirror(surface_buffer);
328 // surface=surface_buffer;