decoder::decoder(std::streambuf *sbuf, info &i) : input_(sbuf), png_(png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)), info_(png_create_info_struct(png_)), end_(png_create_info_struct(png_)) { png_byte header[magic_]; input_->sgetn((char*)header, magic_); if (png_sig_cmp(header, 0, magic_)) throw std::runtime_error("Not a PNG file"); png_set_sig_bytes(png_, magic_); png_set_read_fn(png_, input_, decoder_read); png_set_error_fn(png_, input_, decoder_error, decoder_warning); png_set_read_status_fn(png_, 0); png_read_info(png_, info_); png_uint_32 w, h; int d, c, in, co, f; png_get_IHDR(png_, info_, &w, &h, &d, &c, &in, &co, &f); i.width = w; i.height = h; i.rowbytes = png_get_rowbytes(png_, info_); i.depth = d; i.colortype = static_cast<color_type>(c); i.compression = co; i.filter = f; i.interlace = static_cast<interlace_type>(in); }
char* readpng_image(char* filename, int* width, int* height, int *alpha) { FILE* fp = fopen(filename, "rb"); const int number = 8; png_structp png_ptr; png_infop info_ptr, end_info; png_bytepp row_pointers; unsigned char header[8]; int is_png; int colour_type, bit_depth, image_width, image_height; char* pixels; int x, y; int nchannels; if (!fp) { fprintf(stderr, "Can't load file %s\n", filename); return 0; } fread(header, 1, number, fp); is_png = !png_sig_cmp(header, 0, number); if (!is_png) { fprintf(stderr, "File %s doesn't look like a PNG\n", filename); fclose(fp); return 0; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "Problem creating PNG read struct for %s\n", filename); fclose(fp); return 0; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fprintf(stderr, "Problem creating PNG info struct for %s\n", filename); fclose(fp); return 0; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fprintf(stderr, "Problem creating PNG end struct for %s\n", filename); fclose(fp); return 0; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fprintf(stderr, "Problem loading PNG %s\n", filename); fclose(fp); return 0; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, number); png_set_read_status_fn(png_ptr, read_row_callback); png_read_info(png_ptr, info_ptr); colour_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); image_width = png_get_image_width(png_ptr, info_ptr); image_height = png_get_image_height(png_ptr, info_ptr); if (colour_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_expand(png_ptr); /* update stuff */ png_read_update_info(png_ptr, info_ptr); /* now image data (width, height) etc is ready to be used */ fprintf(stderr, "Reading image: %dx%dx%d\n", image_width, image_height, bit_depth); switch (colour_type) { case PNG_COLOR_TYPE_RGB: nchannels = 3; *alpha = 0; break; case PNG_COLOR_TYPE_RGBA: nchannels = 4; *alpha = 1; break; default: abort (); } row_pointers = calloc(image_height, sizeof(png_bytepp)); for (y=0; y<image_height; y++) { /* FIXME number of channels */ row_pointers[y] = malloc (nchannels * image_width); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, end_info); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); pixels = malloc (nchannels * image_width * image_height); for (y = 0; y < image_height; y++) { char* destrow = &pixels[y * image_width * nchannels]; unsigned char* srcrow = row_pointers[y]; switch (colour_type) { case PNG_COLOR_TYPE_RGB: for (x = 0; x < image_width * 3; x++) destrow[x] = srcrow[x]; break; case PNG_COLOR_TYPE_RGBA: for (x = 0; x < image_width * 4; x++) destrow[x] = srcrow[x]; break; default: abort (); } } for (y = 0; y < image_height; y++) { free (row_pointers[y]); } free (row_pointers); if (width) *width = image_width; if (height) *height = image_height; return pixels; }
/* Test one file */ int test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { static png_FILE_p fpin; static png_FILE_p fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr; png_infop read_info_ptr, end_info_ptr; #ifdef PNG_WRITE_SUPPORTED png_structp write_ptr; png_infop write_info_ptr; png_infop write_end_info_ptr; #else png_structp write_ptr = NULL; png_infop write_info_ptr = NULL; png_infop write_end_info_ptr = NULL; #endif png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif #if defined(_WIN32_WCE) TCHAR path[MAX_PATH]; #endif char inbuf[256], outbuf[256]; row_buf = NULL; #if defined(_WIN32_WCE) MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) #else if ((fpin = fopen(inname, "rb")) == NULL) #endif { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } #if defined(_WIN32_WCE) MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) #else if ((fpout = fopen(outname, "wb")) == NULL) #endif { fprintf(STDERR, "Could not open output file %s\n", outname); FCLOSE(fpin); return (1); } png_debug(0, "Allocating read and write structures\n"); #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); #endif #ifdef PNG_WRITE_SUPPORTED #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); #endif #endif png_debug(0, "Allocating read_info, write_info and end_info structures\n"); read_info_ptr = png_create_info_struct(read_ptr); end_info_ptr = png_create_info_struct(read_ptr); #ifdef PNG_WRITE_SUPPORTED write_info_ptr = png_create_info_struct(write_ptr); write_end_info_ptr = png_create_info_struct(write_ptr); #endif #ifdef PNG_SETJMP_SUPPORTED png_debug(0, "Setting jmpbuf for read struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(read_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); if (row_buf) png_free(read_ptr, row_buf); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); #ifdef PNG_WRITE_SUPPORTED png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); #endif FCLOSE(fpin); FCLOSE(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf)); #endif #ifdef PNG_WRITE_SUPPORTED png_debug(0, "Setting jmpbuf for write struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(write_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr); #ifdef PNG_WRITE_SUPPORTED png_destroy_write_struct(&write_ptr, &write_info_ptr); #endif FCLOSE(fpin); FCLOSE(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf)); #endif #endif #endif png_debug(0, "Initializing input and output streams\n"); #if !defined(PNG_NO_STDIO) png_init_io(read_ptr, fpin); # ifdef PNG_WRITE_SUPPORTED png_init_io(write_ptr, fpout); # endif #else png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); # ifdef PNG_WRITE_SUPPORTED png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, # if defined(PNG_WRITE_FLUSH_SUPPORTED) pngtest_flush); # else NULL); # endif # endif #endif if(status_dots_requested == 1) { #ifdef PNG_WRITE_SUPPORTED png_set_write_status_fn(write_ptr, write_row_callback); #endif png_set_read_status_fn(read_ptr, read_row_callback); } else { #ifdef PNG_WRITE_SUPPORTED png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); #endif png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); } #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) { int i; for(i=0; i<256; i++) filters_used[i]=0; png_set_read_user_transform_fn(read_ptr, count_filters); } #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) zero_samples=0; png_set_write_user_transform_fn(write_ptr, count_zero_samples); #endif #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) # ifndef PNG_HANDLE_CHUNK_ALWAYS # define PNG_HANDLE_CHUNK_ALWAYS 3 # endif png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, png_bytep_NULL, 0); #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) # ifndef PNG_HANDLE_CHUNK_IF_SAFE # define PNG_HANDLE_CHUNK_IF_SAFE 2 # endif png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, png_bytep_NULL, 0); #endif png_debug(0, "Reading info struct\n"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct\n"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, #if defined(PNG_WRITE_INTERLACING_SUPPORTED) color_type, interlace_type, compression_type, filter_type); #else color_type, PNG_INTERLACE_NONE, compression_type, filter_type); #endif } }
int main( int argc, char *argv[] ) { int f, rowbytes; char buf[256]; static FILE *fpout; /* "static" prevents setjmp corruption */ png_structp write_ptr; png_infop write_info_ptr, end_info_ptr; png_bytep row_buf, here; png_uint_32 y; png_textp text_ptr, new_text_ptr; int num_text; int interlace_type, compression_type, filter_type, bit_depth, color_type; int it, ct, ft, bd, clrt; png_uint_32 width, height, w, h; int duration; if( argc < 4 ) { printf( "makeanim v0.2\nusage: makeanim <duration in milliseconds> <input files ...> <output file>\n" ); printf( "example: makeanim 1500 a00.png a01.png a02.png a03.png a04.png a.anim\n" ); return 1; } duration = atoi( argv[1] ); if( duration < 1 ) { printf( "duration is incorrect\n" ); return 1; } numfiles = argc - 3; input = (struct inputstruct *)malloc( sizeof( struct inputstruct ) * numfiles ); if( !input ) return 1; for( f = 0; f < numfiles; f++ ) { input[f].name = argv[f + 2]; printf( "opening file %d, \"%s\"\n", f, input[f].name ); /* open the file handle */ input[f].file = fopen( input[f].name, "rb" ); if( input[f].file == NULL ) { printf( "fopen() failed\n" ); return 1; } /* check if it's PNG */ if( fread( buf, 1, 8, input[f].file ) != 8 ) { printf( "fread() failed for file \"%s\"\n", input[f].name ); return 1; } if( png_sig_cmp( buf, (png_size_t)0, 8 ) ) { printf( "not a PNG file\n" ); return 1; } fseek( input[f].file, 0, SEEK_SET ); /* allocate read structure */ input[f].read_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); if( input[f].read_ptr == NULL ) { printf( "png_create_read_struct() failed\n" ); return 1; } /* allocate read info structure */ input[f].read_info_ptr = png_create_info_struct( input[f].read_ptr ); if( input[f].read_info_ptr == NULL ) { printf( "png_create_info_struct() failed\n" ); return 1; } /* set error handler code */ if( setjmp( input[f].read_ptr->jmpbuf ) ) { printf( "libpng read error\n" ); return 1; } /* initialize stream */ png_init_io( input[f].read_ptr, input[f].file ); png_set_read_status_fn( input[f].read_ptr, NULL ); /* read png info struct */ png_read_info( input[f].read_ptr, input[f].read_info_ptr ); /* get the info */ if( !png_get_IHDR( input[f].read_ptr, input[f].read_info_ptr, &w, &h, &bd, &clrt, &it, &ct, &ft ) ) { printf( "png_get_IHDR() failed\n" ); return 1; } /* save the info of the first frame */ if( f == 0 ) { width = w; height = h; bit_depth = bd; color_type = clrt; interlace_type = it; compression_type = ct; filter_type = ft; } /* compare all other frames to first frame */ else if( (w != width) || (h != height) || (bd != bit_depth) || (clrt != color_type) || (it != interlace_type) || (ct != compression_type) || (ft != filter_type) ) { if( w != width ) printf( "width is different\n" ); if( h != height ) printf( "height is different\n" ); if( bd != bit_depth ) printf( "bit depth is different\n" ); if( clrt != color_type ) printf( "color type is different\n" ); if( it != interlace_type ) printf( "interlace type is different\n" ); if( ct != compression_type ) printf( "compression type is different\n" ); if( ft != filter_type ) printf( "filter type is different\n" ); return 1; } } row_buf = (png_bytep)NULL; /* open output file */ printf( "opening file \"%s\"\n", argv[numfiles + 2] ); fpout = fopen( argv[numfiles + 2], "wb" ); if( fpout == NULL ) { printf( "fopen() failed\n" ); return 1; } /* allocate write structure */ write_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); /* allocate info structures */ write_info_ptr = png_create_info_struct( write_ptr ); end_info_ptr = png_create_info_struct( write_ptr ); /* error handling */ if( setjmp( write_ptr->jmpbuf ) ) { printf( "libpng write error\n" ); return 1; } /* initialize output stream */ png_init_io( write_ptr, fpout ); png_set_write_status_fn( write_ptr, NULL ); /* set info */ png_set_IHDR( write_ptr, write_info_ptr, width * numfiles, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type); /* image characteristics */ { png_color_16p background; double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; double gamma; int intent; png_uint_16p hist; png_uint_32 offset_x, offset_y; int unit_type; png_charp purpose, units; png_charpp params; png_int_32 X0, X1; int type, nparams; png_uint_32 res_x, res_y; png_colorp palette; int num_palette; png_color_8p sig_bit; png_bytep trans; int num_trans; png_color_16p trans_values; /* background color */ if( png_get_bKGD( input[0].read_ptr, input[0].read_info_ptr, &background ) ) { png_set_bKGD( write_ptr, write_info_ptr, background ); } if( png_get_cHRM( input[0].read_ptr, input[0].read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y ) ) { png_set_cHRM( write_ptr, write_info_ptr, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y ); } /* gamma */ if( png_get_gAMA( input[0].read_ptr, input[0].read_info_ptr, &gamma ) ) { png_set_gAMA( write_ptr, write_info_ptr, gamma ); } /* rendering intent */ if( png_get_sRGB( input[0].read_ptr, input[0].read_info_ptr, &intent ) ) { png_set_sRGB( write_ptr, write_info_ptr, intent ); } /* Histogram */ if( png_get_hIST( input[0].read_ptr, input[0].read_info_ptr, &hist ) ) { png_set_hIST( write_ptr, write_info_ptr, hist ); } /* offsets */ if( png_get_oFFs( input[0].read_ptr, input[0].read_info_ptr, &offset_x, &offset_y, &unit_type ) ) { png_set_oFFs( write_ptr, write_info_ptr, offset_x, offset_y, unit_type ); } if( png_get_pCAL( input[0].read_ptr, input[0].read_info_ptr, &purpose, &X0, &X1, &type, &nparams, &units, ¶ms ) ) { png_set_pCAL( write_ptr, write_info_ptr, purpose, X0, X1, type, nparams, units, params ); } /* pixel density */ if( png_get_pHYs( input[0].read_ptr, input[0].read_info_ptr, &res_x, &res_y, &unit_type ) ) { png_set_pHYs( write_ptr, write_info_ptr, res_x, res_y, unit_type ); } /* text chunks */ /* if( png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) > 0 ) { printf( "Handling %d tEXt/zTXt chunks\n", num_text ); png_set_text( write_ptr, write_info_ptr, text_ptr, num_text ); } */ /* palette */ if( png_get_PLTE( input[0].read_ptr, input[0].read_info_ptr, &palette, &num_palette ) ) { png_set_PLTE( write_ptr, write_info_ptr, palette, num_palette ); } /* significant bits */ if( png_get_sBIT( input[0].read_ptr, input[0].read_info_ptr, &sig_bit ) ) { png_set_sBIT( write_ptr, write_info_ptr, sig_bit ); } /* transparency */ if( png_get_tRNS( input[0].read_ptr, input[0].read_info_ptr, &trans, &num_trans, &trans_values ) ) { png_set_tRNS( write_ptr, write_info_ptr, trans, num_trans, trans_values ); } } /* text chunks */ num_text = 0; if( !png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) ) num_text = 0; new_text_ptr = (struct png_text_struct *)malloc( sizeof( struct png_text_struct ) * num_text + 1 ); if( !new_text_ptr ) { printf( "malloc() failed\n" ); return 1; } memcpy( new_text_ptr, text_ptr, sizeof( struct png_text_struct ) * num_text ); snprintf( buf, 255, "SDL_anim %d %d %d", duration, width, numfiles ); buf[255] = 0; new_text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE; new_text_ptr[num_text].key = "format"; new_text_ptr[num_text].text = buf; new_text_ptr[num_text].text_length = strlen( buf ); num_text++; png_set_text( write_ptr, write_info_ptr, new_text_ptr, num_text ); /* write info */ png_write_info( write_ptr, write_info_ptr ); /* allocate buffer */ rowbytes = png_get_rowbytes( input[0].read_ptr, input[0].read_info_ptr ); row_buf = (png_bytep)png_malloc( write_ptr, rowbytes * numfiles ); if( row_buf == NULL ) { printf( "png_malloc() failed\n" ); return 1; } /* copy raw data */ for( y = 0; y < height; y++ ) { /* grab a scanline from each file */ here = row_buf; for( f = 0; f < numfiles; f++ ) { png_read_rows( input[f].read_ptr, (png_bytepp)&here, (png_bytepp)NULL, 1 ); here += rowbytes; } /* write the long scanline */ png_write_rows( write_ptr, (png_bytepp)&row_buf, 1 ); } /* end io */ for( f = 0; f < numfiles; f++ ) png_read_end( input[f].read_ptr, end_info_ptr ); png_write_end( write_ptr, end_info_ptr ); /* cleanup */ png_free( write_ptr, row_buf ); for( f = 0; f < numfiles; f++ ) { png_destroy_read_struct( &input[f].read_ptr, &input[f].read_info_ptr, &end_info_ptr); fclose( input[f].file ); } png_destroy_write_struct( &write_ptr, &write_info_ptr ); fclose( fpout ); return 0; }
/* Test one file */ int test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { static FILE *fpin, *fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr, write_ptr; png_infop read_info_ptr, write_info_ptr, end_info_ptr, write_end_info_ptr; png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmp_env; #endif #endif char inbuf[256], outbuf[256]; row_buf = (png_bytep)NULL; if ((fpin = fopen(inname, "rb")) == NULL) { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } if ((fpout = fopen(outname, "wb")) == NULL) { fprintf(STDERR, "Could not open output file %s\n", outname); fclose(fpin); return (1); } png_debug(0, "Allocating read and write structures\n"); #ifdef PNG_USER_MEM_SUPPORTED read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(read_ptr, (png_voidp)inname, png_default_error, png_default_warning); #endif #ifdef PNG_USER_MEM_SUPPORTED write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(write_ptr, (png_voidp)inname, png_default_error, png_default_warning); #endif png_debug(0, "Allocating read_info, write_info and end_info structures\n"); read_info_ptr = png_create_info_struct(read_ptr); write_info_ptr = png_create_info_struct(write_ptr); end_info_ptr = png_create_info_struct(read_ptr); write_end_info_ptr = png_create_info_struct(write_ptr); #ifdef PNG_USER_MEM_SUPPORTED #endif #ifdef PNG_SETJMP_SUPPORTED png_debug(0, "Setting jmp_env for read struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmp_env)) #else if (setjmp(png_jmp_env(read_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); fclose(fpin); fclose(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmp_env(read_ptr),jmp_env,sizeof(jmp_buf)); #endif png_debug(0, "Setting jmp_env for write struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmp_env)) #else if (setjmp(png_jmp_env(write_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); fclose(fpin); fclose(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmp_env(write_ptr),jmp_env,sizeof(jmp_buf)); #endif #endif png_debug(0, "Initializing input and output streams\n"); #if !defined(PNG_NO_STDIO) png_init_io(read_ptr, fpin); png_init_io(write_ptr, fpout); #else png_set_read_fn(read_ptr, (png_voidp)fpin, png_default_read_data); png_set_write_fn(write_ptr, (png_voidp)fpout, png_default_write_data, #if defined(PNG_WRITE_FLUSH_SUPPORTED) png_default_flush); #else NULL); #endif #endif if(status_dots_requested == 1) { png_set_write_status_fn(write_ptr, write_row_callback); png_set_read_status_fn(read_ptr, read_row_callback); } else { png_set_write_status_fn(write_ptr, NULL); png_set_read_status_fn(read_ptr, NULL); } #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) { int i; for(i=0; i<256; i++) filters_used[i]=0; png_set_read_user_transform_fn(read_ptr, count_filters); } #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) zero_samples=0; png_set_write_user_transform_fn(write_ptr, count_zero_samples); #endif #define HANDLE_CHUNK_IF_SAFE 2 #define HANDLE_CHUNK_ALWAYS 3 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) png_set_keep_unknown_chunks(read_ptr, HANDLE_CHUNK_ALWAYS, NULL, 0); #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) png_set_keep_unknown_chunks(write_ptr, HANDLE_CHUNK_IF_SAFE, NULL, 0); #endif png_debug(0, "Reading info struct\n"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct\n"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, #if defined(PNG_WRITE_INTERLACING_SUPPORTED) color_type, interlace_type, compression_type, filter_type); #else color_type, PNG_INTERLACE_NONE, compression_type, filter_type); #endif } }
int loadpng (char *file_name, int *w, int *h, unsigned int ***buf) { FILE *fp; png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_type; int rowbytes; png_structp png_ptr; png_infop info_ptr; png_infop end_info; int x, y; unsigned int **row_pointers; /* OUVERTURE DU FICHIER */ fp = fopen (file_name, "rb"); if (!fp) { // fprintf (stderr, "Couldn't open file\n"); return 1; } /* CREATION DES STRUCTURES */ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL); if (!png_ptr) { fprintf (stderr, "Memory error\n"); return 1; } info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { png_destroy_read_struct (&png_ptr, (png_infopp) NULL, (png_infopp) NULL); fprintf (stderr, "Read error 1\n"); return 1; } end_info = png_create_info_struct (png_ptr); if (!end_info) { png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL); fprintf (stderr, "Read error 2\n"); return 1; } /* CHARGEMENT DE L'IMAGE */ if (setjmp (png_ptr->jmpbuf)) { png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); fclose (fp); fprintf (stderr, "Erreur de chargement\n"); return 1; } png_init_io (png_ptr, fp); png_set_read_status_fn (png_ptr, NULL); png_read_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); /* printf ("taille : %dx%d\n",width,height); printf ("depth : %d\n",bit_depth); printf ("color type : "); switch (color_type) { case PNG_COLOR_TYPE_GRAY: printf ("PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16)\n"); break; case PNG_COLOR_TYPE_GRAY_ALPHA: printf ("PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16)\n"); break; case PNG_COLOR_TYPE_PALETTE: printf ("PNG_COLOR_TYPE_PALETTE (bit depths 1, 2, 4, 8)\n"); break; case PNG_COLOR_TYPE_RGB: printf ("PNG_COLOR_TYPE_RGB (bit_depths 8, 16)\n"); break; case PNG_COLOR_TYPE_RGB_ALPHA: printf ("PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16)\n"); break; } */ // printf ("PNG_COLOR_MASK_ALPHA : %x\n", PNG_COLOR_MASK_ALPHA); // printf ("PNG_COLOR_MASK_COLOR : %x\n", PNG_COLOR_MASK_COLOR); // printf ("PNG_COLOR_MASK_PALETTE : %x\n", PNG_COLOR_MASK_PALETTE); if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_palette_to_rgb (png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8 (png_ptr); else if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr); if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); png_read_update_info (png_ptr, info_ptr); // printf ("channels : %d\n", png_get_channels (png_ptr, info_ptr)); rowbytes = png_get_rowbytes (png_ptr, info_ptr); // printf ("rowbytes : %d\n", rowbytes); row_pointers = (unsigned int **) malloc (height * sizeof (unsigned int *)); for (y = 0; y < height; y++) row_pointers[y] = (unsigned int *) malloc (4 * width); png_read_image (png_ptr, (png_bytepp) row_pointers); // for (y=0;y<height;y++) { // for (x=0;x<width;x++) { // if (row_pointers[y][x] & 0xf000) // printf ("%x ",(((unsigned int**)row_pointers)[y][x])&0xf); // else // printf (" "); // } // printf ("\n"); // } png_read_end (png_ptr, end_info); png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); (*buf) = (unsigned int **) malloc (height * sizeof (void *)); for (y = 0; y < height; y++) { (*buf)[y] = (unsigned int *) malloc (width * 4); for (x = 0; x < width; x++) (*buf)[y][x] = row_pointers[y][x]; } *w = width; *h = height; return 0; }
int ExtractBits(PNG_CONST TCHAR *inname, PNG_CONST TCHAR *outname) { static HANDLE fpin; static HANDLE fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr; png_infop read_info_ptr, end_info_ptr; png_structp write_ptr = NULL; png_infop write_info_ptr = NULL; png_infop write_end_info_ptr = NULL; png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; char inbuf[256], outbuf[256]; row_buf = NULL; if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } if ((fpout = CreateFile(outname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not open output file %s\n", outname); FCLOSE(fpin); return (1); } png_debug(0, "Allocating read and write structures"); read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); png_debug(0, "Allocating read_info, write_info and end_info structures"); read_info_ptr = png_create_info_struct(read_ptr); end_info_ptr = png_create_info_struct(read_ptr); png_debug(0, "Setting jmpbuf for read struct"); if (setjmp(png_jmpbuf(read_ptr))) { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); png_free(read_ptr, row_buf); row_buf = NULL; png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); FCLOSE(fpin); FCLOSE(fpout); return (1); } png_debug(0, "Initializing input and output streams"); png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); if (status_dots_requested == 1) { png_set_read_status_fn(read_ptr, read_row_callback); } else { png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); } png_debug(0, "Reading info struct"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type); } } { int intent; if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) png_set_sRGB(write_ptr, write_info_ptr, intent); } { png_colorp palette; int num_palette; if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); } { png_color_8p sig_bit; if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) png_set_sBIT(write_ptr, write_info_ptr, sig_bit); } { png_bytep trans; int num_trans; png_color_16p trans_values; if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, &trans_values)) { int sample_max = (1 << read_info_ptr->bit_depth); /* libpng doesn't reject a tRNS chunk with out-of-range samples */ if (!((read_info_ptr->color_type == PNG_COLOR_TYPE_GRAY && (int)trans_values->gray > sample_max) || (read_info_ptr->color_type == PNG_COLOR_TYPE_RGB && ((int)trans_values->red > sample_max || (int)trans_values->green > sample_max || (int)trans_values->blue > sample_max)))) png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, trans_values); } } png_debug(0, "Writing row data"); num_pass = png_set_interlace_handling(read_ptr); for(pass = 0; pass < num_pass; pass++) { png_debug1(0, "Writing row data for pass %d", pass); for(y = 0; y < height; y++) { png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y); row_buf = (png_bytep)png_malloc(read_ptr, png_get_rowbytes(read_ptr, read_info_ptr)); png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf, png_get_rowbytes(read_ptr, read_info_ptr)); png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y); png_free(read_ptr, row_buf); row_buf = NULL; } } png_debug(0, "Reading and writing end_info data"); png_read_end(read_ptr, end_info_ptr); { png_uint_32 iwidth, iheight; iwidth = png_get_image_width(write_ptr, write_info_ptr); iheight = png_get_image_height(write_ptr, write_info_ptr); fprintf(STDERR, "\n Image width = %lu, height = %lu\n", (unsigned long)iwidth, (unsigned long)iheight); } png_debug(0, "Destroying data structs"); png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr"); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_debug(0, "Destruction complete."); FCLOSE(fpin); FCLOSE(fpout); png_debug(0, "Opening files for comparison"); if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find file %s\n", inname); return (1); } if ((fpout = CreateFile(outname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find file %s\n", outname); FCLOSE(fpin); return (1); } for(;;) { DWORD num_in, num_out; READFILE(fpin, inbuf, 1, num_in); READFILE(fpout, outbuf, 1, num_out); if (num_in != num_out) { fprintf(STDERR, "\nFiles %s and %s are of a different size\n", inname, outname); if (wrote_question == 0) { fprintf(STDERR, " Was %s written with the same maximum IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); fprintf(STDERR, "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, " level (zlib default),\n and zlib version (%s)?\n\n", ZLIB_VERSION); wrote_question = 1; } FCLOSE(fpin); FCLOSE(fpout); return (0); } if (!num_in) break; if (png_memcmp(inbuf, outbuf, num_in)) { fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); if (wrote_question == 0) { fprintf(STDERR, " Was %s written with the same maximum IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); fprintf(STDERR, "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, " level (zlib default),\n and zlib version (%s)?\n\n", ZLIB_VERSION); wrote_question = 1; } FCLOSE(fpin); FCLOSE(fpout); return (0); } } FCLOSE(fpin); FCLOSE(fpout); return (0); }
//--------------------------------------------------------------------------- void __fastcall TDeePNG::LoadFromStream(Classes::TStream * Stream) { // LoadFromStream png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_infop end_info = NULL; png_bytep *row_pointers = NULL; BYTE *image = NULL; png_uint_32 i; try { // create png_struct png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)this, DeePNG_error, DeePNG_warning, (png_voidp)this, DeePNG_malloc, DeePNG_free); // set read_chunk_callback png_set_read_user_chunk_fn(png_ptr, reinterpret_cast<void*>(this), PNG_read_chunk_callback); png_set_keep_unknown_chunks(png_ptr, 2, NULL, 0); // keep only if safe-to-copy chunks, for all unknown chunks // create png_info info_ptr = png_create_info_struct(png_ptr); // create end_info end_info = png_create_info_struct(png_ptr); // set stream input functions png_set_read_fn(png_ptr, (voidp)Stream, DeePNG_read_data); // set read_row_callback png_set_read_status_fn(png_ptr, DeePNG_read_row_callback); // call png_read_info png_read_info(png_ptr, info_ptr); // retrieve IHDR png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_type; png_get_IHDR(png_ptr,info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); // expand palletted image which has transparent color, to 32bpp if (png_get_valid(png_ptr, info_ptr,PNG_INFO_tRNS)) { png_set_expand(png_ptr); color_type=PNG_COLOR_TYPE_RGB_ALPHA; } // analyse IHDR ( color_type ) switch(color_type) { case PNG_COLOR_TYPE_GRAY_ALPHA: PixelFormat=pf32bit; break; case PNG_COLOR_TYPE_GRAY: // w/b SetGrayscalePalette(this,bit_depth); break; case PNG_COLOR_TYPE_PALETTE: SetColorDepth(this,bit_depth); break; case PNG_COLOR_TYPE_RGB_ALPHA: PixelFormat=pf32bit; break; case PNG_COLOR_TYPE_RGB: PixelFormat=pf24bit; break; default: throw EDeePNG("EDeePNG : Non-supported color type."); } // retrieve offset information png_int_32 offset_x, offset_y; int offset_unit_type; if(png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &offset_unit_type)) { ofs_x = offset_x; ofs_y = offset_y; ofs_unit = offset_unit_type; ofs_set = true; } else { ofs_set = false; } // check size if(width>=65536 || height>=65536) { throw EDeePNG("EDeePNG : Too large image size."); } // retrieve palette if(color_type == PNG_COLOR_TYPE_PALETTE) { int num_palette; png_color *palette = NULL; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); int i; #pragma pack(push, 1) struct { WORD palVersion; WORD palNumEntries; PALETTEENTRY entry[256]; } pal; #pragma pack(pop) pal.palVersion = 0x300; pal.palNumEntries = num_palette; for(i = 0; i < num_palette; i++) { pal.entry[i].peRed = palette[i].red; pal.entry[i].peGreen = palette[i].green; pal.entry[i].peBlue = palette[i].blue; pal.entry[i].peFlags = 0; } Palette = CreatePalette((const LOGPALETTE*)&pal); } // collapse 16bit precision data to 8bit if(bit_depth == 16) png_set_strip_16(png_ptr); // change color component order if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); // call png_read_update_info ... png_read_update_info(png_ptr, info_ptr); // set size Width=width, Height=height; // allocate memory for row_pointers row_pointers = new png_bytep[height]; png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); image = new BYTE[rowbytes*height]; for(i = 0;i < height; i++) { row_pointers[i] = image + i*rowbytes; } // load image png_read_image(png_ptr, row_pointers); // finish loading image png_read_end(png_ptr, info_ptr); // set image to ScanLines BYTE *imageptr = image; if(color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { // IA IA IA .... for(i = 0; i < height; i++) { BYTE *scanptr = (BYTE*)ScanLine[i]; png_uint_32 j; for(j = 0; j < width; j++) { BYTE i = *(imageptr++); scanptr[0] = i; scanptr[1] = i; scanptr[2] = i; scanptr[3] = *(imageptr++); scanptr += 4; } } } else { // intact copy for(i = 0; i < height; i++) { BYTE *scanptr = (BYTE*)ScanLine[i]; memcpy(scanptr, imageptr, rowbytes); imageptr += rowbytes; } } } catch(...) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); if(row_pointers) delete [] row_pointers; if(image) delete [] image; throw; } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); if(row_pointers) delete [] row_pointers; if(image) delete [] image; }