X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4946a942d77cf51e00aa56404756e124d7c11411..3225a4b8b8656f25dac6cb20684a3c2c273cf796:/src/png/pngwrite.c diff --git a/src/png/pngwrite.c b/src/png/pngwrite.c index ff62395cf4..0252051989 100644 --- a/src/png/pngwrite.c +++ b/src/png/pngwrite.c @@ -1,17 +1,21 @@ /* pngwrite.c - general routines to write a PNG file * - * libpng 1.2.4 - July 8, 2002 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2002 Glenn Randers-Pehrson + * Last changed in libpng 1.4.0 [January 3, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h */ -/* get internal access to png.h */ -#define PNG_INTERNAL +/* Get internal access to png.h */ +#define PNG_NO_PEDANTIC_WARNINGS #include "png.h" #ifdef PNG_WRITE_SUPPORTED +#include "pngpriv.h" /* Writes all the PNG information. This is the suggested way to use the * library. If you have a new chunk to add, make a function to write it, @@ -25,29 +29,35 @@ void PNGAPI png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) { - png_debug(1, "in png_write_info_before_PLTE\n"); + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) { - png_write_sig(png_ptr); /* write PNG signature */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) + /* Write PNG signature */ + png_write_sig(png_ptr); +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) { - png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n"); - png_ptr->mng_features_permitted=0; + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; } #endif - /* write IHDR information. */ + /* Write IHDR information. */ png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, info_ptr->filter_type, -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +#ifdef PNG_WRITE_INTERLACING_SUPPORTED info_ptr->interlace_type); #else 0); #endif - /* the rest of these check to see if the valid field has the appropriate - flag set, and if it does, writes the chunk. */ -#if defined(PNG_WRITE_gAMA_SUPPORTED) + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + */ +#ifdef PNG_WRITE_gAMA_SUPPORTED if (info_ptr->valid & PNG_INFO_gAMA) { # ifdef PNG_FLOATING_POINT_SUPPORTED @@ -59,20 +69,20 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) #endif } #endif -#if defined(PNG_WRITE_sRGB_SUPPORTED) +#ifdef PNG_WRITE_sRGB_SUPPORTED if (info_ptr->valid & PNG_INFO_sRGB) png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); #endif -#if defined(PNG_WRITE_iCCP_SUPPORTED) +#ifdef PNG_WRITE_iCCP_SUPPORTED if (info_ptr->valid & PNG_INFO_iCCP) png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); #endif -#if defined(PNG_WRITE_sBIT_SUPPORTED) +#ifdef PNG_WRITE_sBIT_SUPPORTED if (info_ptr->valid & PNG_INFO_sBIT) png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); #endif -#if defined(PNG_WRITE_cHRM_SUPPORTED) +#ifdef PNG_WRITE_cHRM_SUPPORTED if (info_ptr->valid & PNG_INFO_cHRM) { #ifdef PNG_FLOATING_POINT_SUPPORTED @@ -92,26 +102,29 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) #endif } #endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED if (info_ptr->unknown_chunks_num) { - png_unknown_chunk *up; - - png_debug(5, "writing extra chunks\n"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != HANDLE_CHUNK_NEVER && - up->location && (!(up->location & PNG_HAVE_PLTE)) && - ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS || + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) { + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); png_write_chunk(png_ptr, up->name, up->data, up->size); } - } + } } #endif png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; @@ -125,7 +138,10 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) int i; #endif - png_debug(1, "in png_write_info\n"); + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; png_write_info_before_PLTE(png_ptr, info_ptr); @@ -133,87 +149,94 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) png_write_PLTE(png_ptr, info_ptr->palette, (png_uint_32)info_ptr->num_palette); else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Valid palette required for paletted images\n"); + png_error(png_ptr, "Valid palette required for paletted images"); -#if defined(PNG_WRITE_tRNS_SUPPORTED) +#ifdef PNG_WRITE_tRNS_SUPPORTED if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel (in tRNS) */ - if ((png_ptr->transformations & PNG_INVERT_ALPHA) && - info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - int j; - for (j=0; j<(int)info_ptr->num_trans; j++) - info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); - } + int j; + for (j = 0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans_alpha[j] = (png_byte)(255 - info_ptr->trans_alpha[j]); + } #endif - png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), info_ptr->num_trans, info_ptr->color_type); - } + } #endif -#if defined(PNG_WRITE_bKGD_SUPPORTED) +#ifdef PNG_WRITE_bKGD_SUPPORTED if (info_ptr->valid & PNG_INFO_bKGD) png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); #endif -#if defined(PNG_WRITE_hIST_SUPPORTED) +#ifdef PNG_WRITE_hIST_SUPPORTED if (info_ptr->valid & PNG_INFO_hIST) png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); #endif -#if defined(PNG_WRITE_oFFs_SUPPORTED) +#ifdef PNG_WRITE_oFFs_SUPPORTED if (info_ptr->valid & PNG_INFO_oFFs) png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, info_ptr->offset_unit_type); #endif -#if defined(PNG_WRITE_pCAL_SUPPORTED) +#ifdef PNG_WRITE_pCAL_SUPPORTED if (info_ptr->valid & PNG_INFO_pCAL) png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, info_ptr->pcal_units, info_ptr->pcal_params); #endif -#if defined(PNG_WRITE_sCAL_SUPPORTED) + +#ifdef PNG_sCAL_SUPPORTED if (info_ptr->valid & PNG_INFO_sCAL) -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +#ifdef PNG_WRITE_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); -#else +#else /* !FLOATING_POINT */ #ifdef PNG_FIXED_POINT_SUPPORTED png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, info_ptr->scal_s_width, info_ptr->scal_s_height); -#else +#endif /* FIXED_POINT */ +#endif /* FLOATING_POINT */ +#else /* !WRITE_sCAL */ png_warning(png_ptr, - "png_write_sCAL not supported; sCAL chunk not written.\n"); -#endif -#endif -#endif -#if defined(PNG_WRITE_pHYs_SUPPORTED) + "png_write_sCAL not supported; sCAL chunk not written"); +#endif /* WRITE_sCAL */ +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED if (info_ptr->valid & PNG_INFO_pHYs) png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); -#endif -#if defined(PNG_WRITE_tIME_SUPPORTED) +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED if (info_ptr->valid & PNG_INFO_tIME) { png_write_tIME(png_ptr, &(info_ptr->mod_time)); png_ptr->mode |= PNG_WROTE_tIME; } -#endif -#if defined(PNG_WRITE_sPLT_SUPPORTED) +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED if (info_ptr->valid & PNG_INFO_sPLT) for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); -#endif -#if defined(PNG_WRITE_TEXT_SUPPORTED) +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED /* Check to see if we need to write text chunks */ for (i = 0; i < info_ptr->num_text; i++) { - png_debug2(2, "Writing header text chunk %d, type %d\n", i, + png_debug2(2, "Writing header text chunk %d, type %d", i, info_ptr->text[i].compression); - /* an internationalized chunk? */ + /* An internationalized chunk? */ if (info_ptr->text[i].compression > 0) { -#if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ png_write_iTXt(png_ptr, info_ptr->text[i].compression, info_ptr->text[i].key, @@ -221,7 +244,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) info_ptr->text[i].lang_key, info_ptr->text[i].text); #else - png_warning(png_ptr, "Unable to write international text\n"); + png_warning(png_ptr, "Unable to write international text"); #endif /* Mark this chunk as written */ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; @@ -229,53 +252,55 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) /* If we want a compressed text chunk */ else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) { -#if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ png_write_zTXt(png_ptr, info_ptr->text[i].key, info_ptr->text[i].text, 0, info_ptr->text[i].compression); #else - png_warning(png_ptr, "Unable to write compressed text\n"); + png_warning(png_ptr, "Unable to write compressed text"); #endif /* Mark this chunk as written */ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; } else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) { -#if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ png_write_tEXt(png_ptr, info_ptr->text[i].key, info_ptr->text[i].text, 0); -#else - png_warning(png_ptr, "Unable to write uncompressed text\n"); -#endif /* Mark this chunk as written */ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif } } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED if (info_ptr->unknown_chunks_num) { - png_unknown_chunk *up; + png_unknown_chunk *up; - png_debug(5, "writing extra chunks\n"); + png_debug(5, "writing extra chunks"); - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != HANDLE_CHUNK_NEVER && + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && up->location && (up->location & PNG_HAVE_PLTE) && !(up->location & PNG_HAVE_IDAT) && - ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS || + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) { png_write_chunk(png_ptr, up->name, up->data, up->size); } - } + } } #endif } @@ -288,66 +313,69 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) void PNGAPI png_write_end(png_structp png_ptr, png_infop info_ptr) { - png_debug(1, "in png_write_end\n"); + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; if (!(png_ptr->mode & PNG_HAVE_IDAT)) png_error(png_ptr, "No IDATs written into file"); - /* see if user wants us to write information chunks */ + /* See if user wants us to write information chunks */ if (info_ptr != NULL) { -#if defined(PNG_WRITE_TEXT_SUPPORTED) +#ifdef PNG_WRITE_TEXT_SUPPORTED int i; /* local index variable */ #endif -#if defined(PNG_WRITE_tIME_SUPPORTED) - /* check to see if user has supplied a time chunk */ +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ if ((info_ptr->valid & PNG_INFO_tIME) && !(png_ptr->mode & PNG_WROTE_tIME)) png_write_tIME(png_ptr, &(info_ptr->mod_time)); #endif -#if defined(PNG_WRITE_TEXT_SUPPORTED) - /* loop through comment chunks */ +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ for (i = 0; i < info_ptr->num_text; i++) { - png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, + png_debug2(2, "Writing trailer text chunk %d, type %d", i, info_ptr->text[i].compression); - /* an internationalized chunk? */ + /* An internationalized chunk? */ if (info_ptr->text[i].compression > 0) { -#if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); #else - png_warning(png_ptr, "Unable to write international text\n"); + png_warning(png_ptr, "Unable to write international text"); #endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; } else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) { -#if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ png_write_zTXt(png_ptr, info_ptr->text[i].key, info_ptr->text[i].text, 0, info_ptr->text[i].compression); #else - png_warning(png_ptr, "Unable to write compressed text\n"); + png_warning(png_ptr, "Unable to write compressed text"); #endif /* Mark this chunk as written */ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; } else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) { -#if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ png_write_tEXt(png_ptr, info_ptr->text[i].key, info_ptr->text[i].text, 0); #else - png_warning(png_ptr, "Unable to write uncompressed text\n"); + png_warning(png_ptr, "Unable to write uncompressed text"); #endif /* Mark this chunk as written */ @@ -355,48 +383,55 @@ png_write_end(png_structp png_ptr, png_infop info_ptr) } } #endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED if (info_ptr->unknown_chunks_num) { - png_unknown_chunk *up; + png_unknown_chunk *up; - png_debug(5, "writing extra chunks\n"); + png_debug(5, "writing extra chunks"); - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != HANDLE_CHUNK_NEVER && + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && up->location && (up->location & PNG_AFTER_IDAT) && - ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS || + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) { png_write_chunk(png_ptr, up->name, up->data, up->size); } - } + } } #endif } png_ptr->mode |= PNG_AFTER_IDAT; - /* write end of PNG file */ + /* Write end of PNG file */ png_write_IEND(png_ptr); -#if 0 -/* This flush, added in libpng-1.0.8, causes some applications to crash - because they do not set png_ptr->output_flush_fn */ + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED png_flush(png_ptr); +# endif #endif } -#if defined(PNG_WRITE_tIME_SUPPORTED) -#if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* "tm" structure is not supported on WindowsCE */ void PNGAPI png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) { - png_debug(1, "in png_convert_from_struct_tm\n"); + png_debug(1, "in png_convert_from_struct_tm"); + ptime->year = (png_uint_16)(1900 + ttime->tm_year); ptime->month = (png_byte)(ttime->tm_mon + 1); ptime->day = (png_byte)ttime->tm_mday; @@ -410,12 +445,12 @@ png_convert_from_time_t(png_timep ptime, time_t ttime) { struct tm *tbuf; - png_debug(1, "in png_convert_from_time_t\n"); + png_debug(1, "in png_convert_from_time_t"); + tbuf = gmtime(&ttime); png_convert_from_struct_tm(ptime, tbuf); } #endif -#endif /* Initialize png_ptr structure, and allocate any memory needed */ png_structp PNGAPI @@ -424,7 +459,7 @@ png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, { #ifdef PNG_USER_MEM_SUPPORTED return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); + warn_fn, NULL, NULL, NULL)); } /* Alternate initialize png_ptr structure, and allocate any memory needed */ @@ -434,6 +469,10 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) { #endif /* PNG_USER_MEM_SUPPORTED */ + volatile int png_cleanup_needed = 0; +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif png_structp png_ptr; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD @@ -441,7 +480,9 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, #endif #endif int i; - png_debug(1, "in png_create_write_struct\n"); + + png_debug(1, "in png_create_write_struct"); + #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); @@ -451,27 +492,25 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, if (png_ptr == NULL) return (NULL); -#if !defined(PNG_1_0_X) -#ifdef PNG_ASSEMBLER_CODE_SUPPORTED - png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; #endif -#endif /* PNG_1_0_X */ #ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else - if (setjmp(png_ptr->jmpbuf)) + if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ #endif - { - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf=NULL; - png_destroy_struct(png_ptr); - return (NULL); - } #ifdef USE_FAR_KEYWORD - png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf)); #endif + PNG_ABORT(); #endif #ifdef PNG_USER_MEM_SUPPORTED @@ -479,12 +518,15 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, #endif /* PNG_USER_MEM_SUPPORTED */ png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); - i=0; - do + if (user_png_ver) { - if(user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); + i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { @@ -497,173 +539,63 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) +#ifdef PNG_STDIO_SUPPORTED char msg[80]; if (user_png_ver) { - sprintf(msg, "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); } - sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; + png_ptr->flags = 0; #endif - png_error(png_ptr, + png_warning(png_ptr, "Incompatible libpng version in application and library"); + png_cleanup_needed = 1; } } - /* initialize zbuf - compression buffer */ + /* Initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - - png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* Applications that neglect to set up their own setjmp() and then encounter - a png_error() will longjmp here. Since the jmpbuf is then meaningless we - abort instead of returning. */ -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) - PNG_ABORT(); - png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); -#else - if (setjmp(png_ptr->jmpbuf)) - PNG_ABORT(); -#endif -#endif - return (png_ptr); -} - -/* Initialize png_ptr structure, and allocate any memory needed */ -#undef png_write_init -void PNGAPI -png_write_init(png_structp png_ptr) -{ - /* We only come here via pre-1.0.7-compiled applications */ - png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); -} - -void PNGAPI -png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size, png_size_t png_info_size) -{ - /* We only come here via pre-1.0.12-compiled applications */ -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - if(sizeof(png_struct) > png_struct_size || sizeof(png_info) > png_info_size) + if (!png_cleanup_needed) { - char msg[80]; - png_ptr->warning_fn=NULL; - if (user_png_ver) - { - sprintf(msg, "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - sprintf(msg, "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, + png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; } -#endif - if(sizeof(png_struct) > png_struct_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The png struct allocated by the application for writing is too small."); - } - if(sizeof(png_info) > png_info_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The info struct allocated by the application for writing is too small."); - } - png_write_init_3(&png_ptr, user_png_ver, png_struct_size); -} - - -void PNGAPI -png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size) -{ - png_structp png_ptr=*ptr_ptr; -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* to save current jump buffer */ -#endif - int i = 0; - do + if (png_cleanup_needed) { - if (user_png_ver[i] != png_libpng_ver[i]) - { -#ifdef PNG_LEGACY_SUPPORTED - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); #else - png_ptr->warning_fn=NULL; - png_warning(png_ptr, - "Application uses deprecated png_write_init() and should be recompiled."); - break; -#endif - } - } while (png_libpng_ver[i++]); - - png_debug(1, "in png_write_init_3\n"); - -#ifdef PNG_SETJMP_SUPPORTED - /* save jump buffer and error functions */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); -#endif - - if (sizeof(png_struct) > png_struct_size) - { - png_destroy_struct(png_ptr); - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); - *ptr_ptr = png_ptr; - } - - /* reset all variables to 0 */ - png_memset(png_ptr, 0, sizeof (png_struct)); - -#if !defined(PNG_1_0_X) -#ifdef PNG_ASSEMBLER_CODE_SUPPORTED - png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ -#endif -#endif /* PNG_1_0_X */ - -#ifdef PNG_SETJMP_SUPPORTED - /* restore jump buffer */ - png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); + png_destroy_struct((png_voidp)png_ptr); #endif + return (NULL); + } - png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); + png_set_write_fn(png_ptr, NULL, NULL, NULL); - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); + 1, NULL, NULL); #endif + + return (png_ptr); } + /* Write a few rows of image data. If the image is interlaced, * either you will have to write the 7 sub images, or, if you * have called png_set_interlace_handling(), you will have to @@ -676,8 +608,12 @@ png_write_rows(png_structp png_ptr, png_bytepp row, png_uint_32 i; /* row counter */ png_bytepp rp; /* row pointer */ - png_debug(1, "in png_write_rows\n"); - /* loop through the rows */ + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ for (i = 0, rp = row; i < num_rows; i++, rp++) { png_write_row(png_ptr, *rp); @@ -694,18 +630,23 @@ png_write_image(png_structp png_ptr, png_bytepp image) int pass, num_pass; /* pass variables */ png_bytepp rp; /* points to current row */ - png_debug(1, "in png_write_image\n"); -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* intialize interlace handling. If image is not interlaced, - this will set pass to 1 */ + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ num_pass = png_set_interlace_handling(png_ptr); #else num_pass = 1; #endif - /* loop through passes */ + /* Loop through passes */ for (pass = 0; pass < num_pass; pass++) { - /* loop through image */ + /* Loop through image */ for (i = 0, rp = image; i < png_ptr->height; i++, rp++) { png_write_row(png_ptr, *rp); @@ -713,55 +654,61 @@ png_write_image(png_structp png_ptr, png_bytepp image) } } -/* called by user to write a row of image data */ +/* Called by user to write a row of image data */ void PNGAPI png_write_row(png_structp png_ptr, png_bytep row) { - png_debug2(1, "in png_write_row (row %ld, pass %d)\n", + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %ld, pass %d)", png_ptr->row_number, png_ptr->pass); - /* initialize transformations and other stuff if first time */ + + /* Initialize transformations and other stuff if first time */ if (png_ptr->row_number == 0 && png_ptr->pass == 0) { - /* make sure we wrote the header info */ - if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - png_error(png_ptr, - "png_write_info was never called before png_write_row."); + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row"); - /* check for transforms that have been set but were defined out */ + /* Check for transforms that have been set but were defined out */ #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); #endif #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); #endif -#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); #endif #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); #endif #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); #endif #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); #endif #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); #endif png_write_start_row(png_ptr); } -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* if interlaced and not interested in row, return */ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) { switch (png_ptr->pass) @@ -819,7 +766,7 @@ png_write_row(png_structp png_ptr, png_bytep row) } #endif - /* set up row info for transformations */ + /* Set up row info for transformations */ png_ptr->row_info.color_type = png_ptr->color_type; png_ptr->row_info.width = png_ptr->usr_width; png_ptr->row_info.channels = png_ptr->usr_channels; @@ -827,28 +774,27 @@ png_write_row(png_structp png_ptr, png_bytep row) png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * png_ptr->row_info.channels); - png_ptr->row_info.rowbytes = ((png_ptr->row_info.width * - (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3); + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); - png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); - png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); - png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels); - png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth); - png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); - png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); + png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %lu", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes); /* Copy user's row into buffer, leaving room for filter byte. */ - png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, - png_ptr->row_info.rowbytes); + png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes); -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* handle interlacing */ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ if (png_ptr->interlaced && png_ptr->pass < 6 && (png_ptr->transformations & PNG_INTERLACE)) { png_do_write_interlace(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr->pass); - /* this should always get caught above, but still ... */ + /* This should always get caught above, but still ... */ if (!(png_ptr->row_info.width)) { png_write_finish_row(png_ptr); @@ -857,11 +803,11 @@ png_write_row(png_structp png_ptr, png_bytep row) } #endif - /* handle other transformations */ + /* Handle other transformations */ if (png_ptr->transformations) png_do_write_transformations(png_ptr); -#if defined(PNG_MNG_FEATURES_SUPPORTED) +#ifdef PNG_MNG_FEATURES_SUPPORTED /* Write filter_method 64 (intrapixel differencing) only if * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and * 2. Libpng did not write a PNG signature (this filter_method is only @@ -871,7 +817,7 @@ png_write_row(png_structp png_ptr, png_bytep row) * 4. The filter_method is 64 and * 5. The color_type is RGB or RGBA */ - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) { /* Intrapixel differencing */ @@ -886,35 +832,41 @@ png_write_row(png_structp png_ptr, png_bytep row) (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); } -#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#ifdef PNG_WRITE_FLUSH_SUPPORTED /* Set the automatic flush interval or 0 to turn flushing off */ void PNGAPI png_set_flush(png_structp png_ptr, int nrows) { - png_debug(1, "in png_set_flush\n"); + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); } -/* flush the current output buffers now */ +/* Flush the current output buffers now */ void PNGAPI png_write_flush(png_structp png_ptr) { int wrote_IDAT; - png_debug(1, "in png_write_flush\n"); + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; /* We have already written out all of the data */ if (png_ptr->row_number >= png_ptr->num_rows) - return; + return; do { int ret; - /* compress the data */ + /* Compress the data */ ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); wrote_IDAT = 0; - /* check for compression errors */ + /* Check for compression errors */ if (ret != Z_OK) { if (png_ptr->zstream.msg != NULL) @@ -925,7 +877,7 @@ png_write_flush(png_structp png_ptr) if (!(png_ptr->zstream.avail_out)) { - /* write the IDAT and reset the zlib output buffer */ + /* Write the IDAT and reset the zlib output buffer */ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); png_ptr->zstream.next_out = png_ptr->zbuf; @@ -937,7 +889,7 @@ png_write_flush(png_structp png_ptr) /* If there is any data left to be output, write it into a new IDAT */ if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) { - /* write the IDAT and reset the zlib output buffer */ + /* Write the IDAT and reset the zlib output buffer */ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); png_ptr->zstream.next_out = png_ptr->zbuf; @@ -948,7 +900,7 @@ png_write_flush(png_structp png_ptr) } #endif /* PNG_WRITE_FLUSH_SUPPORTED */ -/* free all memory used by the write */ +/* Free all memory used by the write */ void PNGAPI png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) { @@ -959,7 +911,8 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) png_voidp mem_ptr = NULL; #endif - png_debug(1, "in png_destroy_write_struct\n"); + png_debug(1, "in png_destroy_write_struct"); + if (png_ptr_ptr != NULL) { png_ptr = *png_ptr_ptr; @@ -969,21 +922,31 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) #endif } +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL) + { + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; + } +#endif + if (info_ptr_ptr != NULL) info_ptr = *info_ptr_ptr; if (info_ptr != NULL) { - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->num_chunk_list) + if (png_ptr != NULL) { - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - png_ptr->num_chunk_list=0; - } + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->num_chunk_list = 0; + } #endif + } #ifdef PNG_USER_MEM_SUPPORTED png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, @@ -1013,7 +976,7 @@ void /* PRIVATE */ png_write_destroy(png_structp png_ptr) { #ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* save jump buffer */ + jmp_buf tmp_jmp; /* Save jump buffer */ #endif png_error_ptr error_fn; png_error_ptr warning_fn; @@ -1022,24 +985,27 @@ png_write_destroy(png_structp png_ptr) png_free_ptr free_fn; #endif - png_debug(1, "in png_write_destroy\n"); - /* free any memory zlib uses */ + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ deflateEnd(&png_ptr->zstream); - /* free our memory. png_free checks NULL for us. */ + /* Free our memory. png_free checks NULL for us. */ png_free(png_ptr, png_ptr->zbuf); png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED png_free(png_ptr, png_ptr->prev_row); png_free(png_ptr, png_ptr->sub_row); png_free(png_ptr, png_ptr->up_row); png_free(png_ptr, png_ptr->avg_row); png_free(png_ptr, png_ptr->paeth_row); +#endif -#if defined(PNG_TIME_RFC1123_SUPPORTED) +#ifdef PNG_TIME_RFC1123_SUPPORTED png_free(png_ptr, png_ptr->time_buffer); #endif -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED png_free(png_ptr, png_ptr->prev_filters); png_free(png_ptr, png_ptr->filter_weights); png_free(png_ptr, png_ptr->inv_filter_weights); @@ -1048,8 +1014,8 @@ png_write_destroy(png_structp png_ptr) #endif #ifdef PNG_SETJMP_SUPPORTED - /* reset structure */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); + /* Reset structure */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); #endif error_fn = png_ptr->error_fn; @@ -1059,7 +1025,7 @@ png_write_destroy(png_structp png_ptr) free_fn = png_ptr->free_fn; #endif - png_memset(png_ptr, 0, sizeof (png_struct)); + png_memset(png_ptr, 0, png_sizeof(png_struct)); png_ptr->error_fn = error_fn; png_ptr->warning_fn = warning_fn; @@ -1069,7 +1035,7 @@ png_write_destroy(png_structp png_ptr) #endif #ifdef PNG_SETJMP_SUPPORTED - png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); #endif } @@ -1077,9 +1043,12 @@ png_write_destroy(png_structp png_ptr) void PNGAPI png_set_filter(png_structp png_ptr, int method, int filters) { - png_debug(1, "in png_set_filter\n"); -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && (method == PNG_INTRAPIXEL_DIFFERENCING)) method = PNG_FILTER_TYPE_BASE; #endif @@ -1087,15 +1056,26 @@ png_set_filter(png_structp png_ptr, int method, int filters) { switch (filters & (PNG_ALL_FILTERS | 0x07)) { +#ifdef PNG_WRITE_FILTER_SUPPORTED case 5: case 6: case 7: png_warning(png_ptr, "Unknown row filter for method 0"); - case PNG_FILTER_VALUE_NONE: png_ptr->do_filter=PNG_FILTER_NONE; break; - case PNG_FILTER_VALUE_SUB: png_ptr->do_filter=PNG_FILTER_SUB; break; - case PNG_FILTER_VALUE_UP: png_ptr->do_filter=PNG_FILTER_UP; break; - case PNG_FILTER_VALUE_AVG: png_ptr->do_filter=PNG_FILTER_AVG; break; - case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break; +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter = PNG_FILTER_NONE; break; +#ifdef PNG_WRITE_FILTER_SUPPORTED + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter = PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter = PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter = PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter = PNG_FILTER_PAETH; break; default: png_ptr->do_filter = (png_byte)filters; break; +#else + default: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ } /* If we have allocated the row_buf, this means we have already started @@ -1109,6 +1089,7 @@ png_set_filter(png_structp png_ptr, int method, int filters) */ if (png_ptr->row_buf != NULL) { +#ifdef PNG_WRITE_FILTER_SUPPORTED if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) { png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, @@ -1163,6 +1144,7 @@ png_set_filter(png_structp png_ptr, int method, int filters) } if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_WRITE_FILTER_SUPPORTED */ png_ptr->do_filter = PNG_FILTER_NONE; } } @@ -1177,7 +1159,7 @@ png_set_filter(png_structp png_ptr, int method, int filters) * filtered data going to zlib more consistent, hopefully resulting in * better compression. */ -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ void PNGAPI png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, int num_weights, png_doublep filter_weights, @@ -1185,7 +1167,10 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, { int i; - png_debug(1, "in png_set_filter_heuristics\n"); + png_debug(1, "in png_set_filter_heuristics"); + + if (png_ptr == NULL) + return; if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) { png_warning(png_ptr, "Unknown filter heuristic method"); @@ -1211,7 +1196,7 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, if (png_ptr->prev_filters == NULL) { png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(sizeof(png_byte) * num_weights)); + (png_uint_32)(png_sizeof(png_byte) * num_weights)); /* To make sure that the weighting starts out fairly */ for (i = 0; i < num_weights; i++) @@ -1223,10 +1208,10 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, if (png_ptr->filter_weights == NULL) { png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(sizeof(png_uint_16) * num_weights)); + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(sizeof(png_uint_16) * num_weights)); + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); for (i = 0; i < num_weights; i++) { png_ptr->inv_filter_weights[i] = @@ -1257,10 +1242,10 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, if (png_ptr->filter_costs == NULL) { png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) { @@ -1297,7 +1282,10 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, void PNGAPI png_set_compression_level(png_structp png_ptr, int level) { - png_debug(1, "in png_set_compression_level\n"); + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; png_ptr->zlib_level = level; } @@ -1305,7 +1293,10 @@ png_set_compression_level(png_structp png_ptr, int level) void PNGAPI png_set_compression_mem_level(png_structp png_ptr, int mem_level) { - png_debug(1, "in png_set_compression_mem_level\n"); + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; png_ptr->zlib_mem_level = mem_level; } @@ -1313,7 +1304,10 @@ png_set_compression_mem_level(png_structp png_ptr, int mem_level) void PNGAPI png_set_compression_strategy(png_structp png_ptr, int strategy) { - png_debug(1, "in png_set_compression_strategy\n"); + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; png_ptr->zlib_strategy = strategy; } @@ -1321,16 +1315,18 @@ png_set_compression_strategy(png_structp png_ptr, int strategy) void PNGAPI png_set_compression_window_bits(png_structp png_ptr, int window_bits) { + if (png_ptr == NULL) + return; if (window_bits > 15) png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); else if (window_bits < 8) png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); #ifndef WBITS_8_OK - /* avoid libpng bug with 256-byte windows */ + /* Avoid libpng bug with 256-byte windows */ if (window_bits == 8) { png_warning(png_ptr, "Compression window is being reset to 512"); - window_bits=9; + window_bits = 9; } #endif png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; @@ -1340,7 +1336,10 @@ png_set_compression_window_bits(png_structp png_ptr, int window_bits) void PNGAPI png_set_compression_method(png_structp png_ptr, int method) { - png_debug(1, "in png_set_compression_method\n"); + png_debug(1, "in png_set_compression_method"); + + if (png_ptr == NULL) + return; if (method != 8) png_warning(png_ptr, "Only compression method 8 is supported by PNG"); png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; @@ -1350,101 +1349,109 @@ png_set_compression_method(png_structp png_ptr, int method) void PNGAPI png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) { + if (png_ptr == NULL) + return; png_ptr->write_row_fn = write_row_fn; } -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED void PNGAPI png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr write_user_transform_fn) { - png_debug(1, "in png_set_write_user_transform_fn\n"); + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; png_ptr->transformations |= PNG_USER_TRANSFORM; png_ptr->write_user_transform_fn = write_user_transform_fn; } #endif -#if defined(PNG_INFO_IMAGE_SUPPORTED) +#ifdef PNG_INFO_IMAGE_SUPPORTED void PNGAPI png_write_png(png_structp png_ptr, png_infop info_ptr, int transforms, voidp params) { -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel from opacity to transparency */ - if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); -#endif + if (png_ptr == NULL || info_ptr == NULL) + return; /* Write the file header information. */ png_write_info(png_ptr, info_ptr); /* ------ these transformations don't touch the info structure ------- */ -#if defined(PNG_WRITE_INVERT_SUPPORTED) - /* invert monochrome pixels */ +#ifdef PNG_WRITE_INVERT_SUPPORTED + /* Invert monochrome pixels */ if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); + png_set_invert_mono(png_ptr); #endif -#if defined(PNG_WRITE_SHIFT_SUPPORTED) +#ifdef PNG_WRITE_SHIFT_SUPPORTED /* Shift the pixels up to a legal bit depth and fill in * as appropriate to correctly scale the image. */ if ((transforms & PNG_TRANSFORM_SHIFT) && (info_ptr->valid & PNG_INFO_sBIT)) - png_set_shift(png_ptr, &info_ptr->sig_bit); + png_set_shift(png_ptr, &info_ptr->sig_bit); #endif -#if defined(PNG_WRITE_PACK_SUPPORTED) - /* pack pixels into bytes */ +#ifdef PNG_WRITE_PACK_SUPPORTED + /* Pack pixels into bytes */ if (transforms & PNG_TRANSFORM_PACKING) png_set_packing(png_ptr); #endif -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - /* swap location of alpha bytes from ARGB to RGBA */ +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + /* Swap location of alpha bytes from ARGB to RGBA */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); + png_set_swap_alpha(png_ptr); #endif -#if defined(PNG_WRITE_FILLER_SUPPORTED) - /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into - * RGB (4 channels -> 3 channels). The second parameter is not used. - */ - if (transforms & PNG_TRANSFORM_STRIP_FILLER) - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#ifdef PNG_WRITE_FILLER_SUPPORTED + /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); #endif -#if defined(PNG_WRITE_BGR_SUPPORTED) - /* flip BGR pixels to RGB */ +#ifdef PNG_WRITE_BGR_SUPPORTED + /* Flip BGR pixels to RGB */ if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); + png_set_bgr(png_ptr); #endif -#if defined(PNG_WRITE_SWAP_SUPPORTED) - /* swap bytes of 16-bit files to most significant byte first */ +#ifdef PNG_WRITE_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to most significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); + png_set_swap(png_ptr); #endif -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) - /* swap bits of 1, 2, 4 bit packed pixel formats */ +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + /* Swap bits of 1, 2, 4 bit packed pixel formats */ if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); #endif /* ----------------------- end of transformations ------------------- */ - /* write the bits */ + /* Write the bits */ if (info_ptr->valid & PNG_INFO_IDAT) png_write_image(png_ptr, info_ptr->row_pointers); /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end(png_ptr, info_ptr); - if(transforms == 0 || params == NULL) - /* quiet compiler warnings */ return; + transforms = transforms; /* Quiet compiler warnings */ + params = params; } #endif #endif /* PNG_WRITE_SUPPORTED */