www.pudn.com > ilib > IPNG.c
/* * IPNG.c * * Image library * * Description: * Implementation of read and write for PNG. * Requires PNG library available at: * http://www.cdrom.com/pub/png/pngcode.html * * Comments: * Still need to implement 8-bit colormap support. (Currently * all images are written out as truecolor which makes them a little * larger.) * Transparency, Alpha channels and interlacing are not yet * supported when writing files. * * History: * 01-Apr-00 Jim Winstead jimw@trainedmonkey.com * Fixed PNG output * 19-Jul-99 Craig Knudsen cknudsen@radix.net * Created * ****************************************************************************/ #ifdef HAVE_PNGLIB #include#include #include #include #include #include "Ilib.h" #include "IlibP.h" IError _IWritePNG ( fp, image, options ) FILE *fp; IImageP *image; IOptions options; { png_structp png_ptr; png_infop info_ptr; png_text comment; int row; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL ); if ( png_ptr == NULL ) return IPNGError; info_ptr = png_create_info_struct ( png_ptr ); if ( setjmp ( png_ptr->jmpbuf ) ) return IPNGError; png_init_io ( png_ptr, fp ); /* TODO: convert to 8-bit palette image instead of always using ** full-color images. */ /* set header info -- the 8 means 8 bits per color, not 8 bits per pixel */ png_set_IHDR ( png_ptr, info_ptr, image->width, image->height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); /* set comment */ if ( image->comments != NULL ) { comment.compression = PNG_TEXT_COMPRESSION_NONE; comment.key = "Comment"; comment.text = image->comments; png_set_text ( png_ptr, info_ptr, &comment, 1 ); } /* write header */ png_write_info ( png_ptr, info_ptr ); /* let libpng take care of bit-depth conversions */ /*png_set_packing ( png_ptr );*/ /* write out image, one row at a time ** we have to convert to PNG's 16-bit format. */ for ( row = 0; row < image->height; row++ ) { png_write_row ( png_ptr, (image->data + image->width * row * 3)); } png_write_end ( png_ptr, info_ptr ); fflush ( fp ); png_destroy_write_struct ( &png_ptr, (png_infopp)NULL ); return ( INoError ); } IError _IReadPNG ( fp, options, image_return ) FILE *fp; IOptions options; IImageP **image_return; { IImageP *image = NULL; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type, row; png_bytep row_pointer; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL ); if ( png_ptr == NULL ) return IPNGError; /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct ( png_ptr ); if ( info_ptr == NULL ) { png_destroy_read_struct ( &png_ptr, (png_infopp)NULL, (png_infopp)NULL ); return ( IPNGError ); } /* setup default error handling */ if ( setjmp ( png_ptr->jmpbuf ) ) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct ( &png_ptr, &info_ptr, (png_infopp)NULL ); return ( IPNGError ); } png_init_io ( png_ptr, fp ); /* read header */ png_read_info ( png_ptr, info_ptr ); png_get_IHDR ( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL ); image = (IImageP *) ICreateImage ( width, height, IOPTION_NONE ); /* Expand paletted colors into true RGB triplets */ if ( color_type == PNG_COLOR_TYPE_PALETTE ) png_set_expand ( png_ptr ); /* Strip alpha bytes from the input data without combining with the ** background (not recommended). */ png_set_strip_alpha ( png_ptr ); /* Read the image one line at a time. That way we don't have to ** malloc two images. */ row_pointer = (png_bytep) png_malloc ( png_ptr, png_get_rowbytes ( png_ptr, info_ptr ) ); row_pointer = (png_bytep) malloc ( image->width * 3 ); for ( row = 0; row < height; row++ ) { png_read_rows ( png_ptr, &row_pointer, NULL, 1 ); memcpy ( image->data + ( row * image->width * 3 ), row_pointer, ( image->width * 3 ) ); } free ( row_pointer ); /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end ( png_ptr, info_ptr ); /* clean up */ png_destroy_read_struct ( &png_ptr, &info_ptr, (png_infopp)NULL ); *image_return = image; return ( INoError ); } #endif /* HAVE_PNGLIB */