summaryrefslogtreecommitdiffstats
path: root/debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx')
-rw-r--r--debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx180
1 files changed, 180 insertions, 0 deletions
diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx
new file mode 100644
index 00000000..c98da9b1
--- /dev/null
+++ b/debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx
@@ -0,0 +1,180 @@
+/************************************************************************
+
+ PNG image file format support.
+
+ The I/O code in this file was originally based on the example.c
+ skeleton code distributed with the PNG library.
+
+ $Id: raster-png.cxx 427 2004-09-27 04:45:31Z garland $
+
+ ************************************************************************/
+
+#include <vector>
+#include <gfx/gfx.h>
+#include <gfx/raster.h>
+
+#ifdef HAVE_LIBPNG
+
+#include <png.h>
+
+namespace gfx
+{
+
+ByteRaster *read_png_image(const char *file_name)
+{
+ FILE *fp = fopen(file_name, "rb");
+ if( !fp ) return NULL;
+
+ // The last three arguments can be used to set up error handling callbacks.
+ png_structp png_ptr =
+ png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if( !png_ptr ) { fclose(fp); return NULL; }
+
+ // Allocate required structure to hold memory information.
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if( !info_ptr )
+ {
+ fclose(fp);
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ return NULL;
+ }
+
+ // Because we didn't set up any error handlers, we need to be
+ // prepared to handle longjmps out of the library on error
+ // conditions.
+ if( setjmp(png_ptr->jmpbuf) )
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ fclose(fp);
+ return NULL;
+ }
+
+ png_init_io(png_ptr, fp);
+
+ // Read in all the image information
+ png_read_info(png_ptr, info_ptr);
+
+ // Get the header for the first image chunk
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type;
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ &interlace_type, NULL, NULL);
+
+
+ ////////////////////////////////////////////////////////////////
+ // the following tell the PNG library how to transform the image
+ // during input
+
+ if( bit_depth == 16 )
+ // truncate 16 bits/pixel to 8 bits/pixel
+ png_set_strip_16(png_ptr);
+
+ if( color_type == PNG_COLOR_TYPE_PALETTE )
+ // expand paletted colors into RGB color values
+ png_set_expand(png_ptr);
+ else if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
+ // expand grayscale images to full 8 bits/pixel
+ png_set_expand(png_ptr);
+
+ // Expand paletted or RGB images with transparency to full alpha
+ // channels so the data will be available as RGBA quartets.
+ if( png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) )
+ png_set_expand(png_ptr);
+
+ // update the palette and info structure
+ png_read_update_info(png_ptr, info_ptr);
+
+
+ // read the image data
+ std::vector<png_bytep> row_pointers(height);
+ int row;
+ int nchan = png_get_channels(png_ptr, info_ptr);
+ int nbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ for (row = 0; row < height; row++)
+ row_pointers[row] = (png_bytep)malloc(nbytes);
+
+ png_read_image(png_ptr, &row_pointers.front());
+ png_read_end(png_ptr, info_ptr);
+
+ // Read it into a ByteRaster structure
+ ByteRaster *img = new ByteRaster(width, height, nchan);
+
+ unsigned char *pixel = img->pixel(0,0);
+ for(row=0; row<height; row++)
+ {
+ memcpy(pixel, row_pointers[row], nbytes);
+ pixel += nbytes;
+ }
+
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ for(row=0; row<height; row++) free(row_pointers[row]);
+
+ fclose(fp);
+ return img;
+}
+
+bool write_png_image(const char *file_name, const ByteRaster& img)
+{
+ FILE *fp = fopen(file_name, "wb");
+ if( !fp ) return false;
+
+ png_structp png_ptr =
+ png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if( !png_ptr ) { fclose(fp); return false; }
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if( !info_ptr )
+ {
+ fclose(fp);
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ return false;
+ }
+
+ if( setjmp(png_ptr->jmpbuf) )
+ {
+ fclose(fp);
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ return false;
+ }
+
+ png_init_io(png_ptr, fp);
+
+ int img_type = PNG_COLOR_TYPE_RGB;
+ switch( img.channels() )
+ {
+ case 1: img_type=PNG_COLOR_TYPE_GRAY; break;
+ case 2: img_type=PNG_COLOR_TYPE_GRAY_ALPHA; break;
+ case 4: img_type=PNG_COLOR_TYPE_RGB_ALPHA; break;
+ }
+
+ png_set_IHDR(png_ptr, info_ptr,
+ img.width(), img.height(), 8, img_type, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_write_info(png_ptr, info_ptr);
+
+ std::vector<png_bytep> row_pointers(img.height());
+ for(int k=0; k<img.height(); k++)
+ row_pointers[k] = (png_bytep)img.head() +k*img.width()*img.channels();
+
+ png_write_image(png_ptr, &row_pointers.front());
+ png_write_end(png_ptr, info_ptr);
+
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ fclose(fp);
+ return true;
+}
+
+} // namespace gfx
+
+#else
+
+namespace gfx
+{
+bool write_png_image(const char *, const ByteRaster&) { return false; }
+ByteRaster *read_png_image(const char *) { return NULL; }
+} // namespace gfx
+
+#endif