diff --git a/ANNOUNCE b/ANNOUNCE index c62a99e23..3ac4ac985 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,5 +1,5 @@ -Libpng 1.5.0beta24 - April 29, 2010 +Libpng 1.5.0beta24 - May 6, 2010 This is not intended to be a public release. It will be replaced within a few weeks by a public version or by another test version. @@ -220,6 +220,11 @@ version 1.5.0beta23 [April 29, 2010] Removed dummy_inflate.c from contrib/pngminim/encoder Removed contrib/pngminim/*/gather.sh; gathering is now done in the makefile. +version 1.5.0beta24 [May 6, 2010] + Use bitwise "&" instead of arithmetic mod in pngrutil.c calculation of the + offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf. + Added more blank lines for readability. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net: (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/CHANGES b/CHANGES index fd1c293c4..16679abb5 100644 --- a/CHANGES +++ b/CHANGES @@ -2702,6 +2702,11 @@ version 1.5.0beta23 [April 29, 2010] Removed dummy_inflate.c from contrib/pngminim/encoder Removed contrib/pngminim/*/gather.sh; gathering is now done in the makefile. +version 1.5.0beta24 [May 6, 2010] + Use bitwise "&" instead of arithmetic mod in pngrutil.c calculation of the + offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf. + Added more blank lines for readability. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/example.c b/example.c index 6523af344..1b97d66ae 100644 --- a/example.c +++ b/example.c @@ -2,7 +2,7 @@ #if 0 /* in case someone actually tries to compile this */ /* example.c - an example of using libpng - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 2010] * This file has been placed in the public domain by the authors. * Maintained 1998-2010 Glenn Randers-Pehrson * Maintained 1996, 1997 Andreas Dilger) @@ -658,14 +658,18 @@ void write_png(char *file_name /* , ... other image information ... */) /* Optional significant bit (sBIT) chunk */ png_color_8 sig_bit; + /* If we are dealing with a grayscale image then */ sig_bit.gray = true_bit_depth; + /* Otherwise, if we are dealing with a color image then */ sig_bit.red = true_red_bit_depth; sig_bit.green = true_green_bit_depth; sig_bit.blue = true_blue_bit_depth; + /* If the image has an alpha channel then */ sig_bit.alpha = true_alpha_bit_depth; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); @@ -757,6 +761,7 @@ void write_png(char *file_name /* , ... other image information ... */) /* Turn on interlace handling if you are not using png_write_image() */ if (interlacing) number_passes = png_set_interlace_handling(png_ptr); + else number_passes = 1; diff --git a/png.c b/png.c index d19802e6d..9b235cf8c 100644 --- a/png.c +++ b/png.c @@ -1,7 +1,7 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -53,8 +53,10 @@ int PNGAPI png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) { png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + if (num_to_check > 8) num_to_check = 8; + else if (num_to_check < 1) return (-1); @@ -81,6 +83,7 @@ png_zalloc(voidpf png_ptr, uInt items, uInt size) if (png_ptr == NULL) return (NULL); + if (items > PNG_UINT_32_MAX/size) { png_warning (p, "Potential overflow in png_zalloc()"); @@ -127,6 +130,7 @@ png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) need_crc = 0; } + else /* critical */ { if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) @@ -234,8 +238,10 @@ png_data_freer(png_structp png_ptr, png_infop info_ptr, if (freer == PNG_DESTROY_WILL_FREE_DATA) info_ptr->free_me |= mask; + else if (freer == PNG_USER_WILL_FREE_DATA) info_ptr->free_me &= ~mask; + else png_warning(png_ptr, "Unknown freer parameter in png_data_freer"); @@ -262,6 +268,7 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, info_ptr->text[num].key = NULL; } } + else { int i; @@ -347,6 +354,7 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, info_ptr->splt_palettes[num].entries = NULL; } } + else { if (info_ptr->splt_palettes_num) @@ -381,6 +389,7 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, info_ptr->unknown_chunks[num].data = NULL; } } + else { int i; @@ -438,6 +447,7 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, if (num == -1) info_ptr->free_me &= ~mask; + else info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); } @@ -475,6 +485,7 @@ png_get_io_ptr(png_structp png_ptr) { if (png_ptr == NULL) return (NULL); + return (png_ptr->io_ptr); } @@ -511,6 +522,7 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) if (png_ptr == NULL) return (NULL); + if (png_ptr->time_buffer == NULL) { png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* @@ -548,13 +560,13 @@ png_get_copyright(png_structp png_ptr) #else # ifdef __STDC__ return ((png_charp) PNG_STRING_NEWLINE \ - "libpng version 1.5.0beta24 - April 29, 2010" PNG_STRING_NEWLINE \ + "libpng version 1.5.0beta24 - May 6, 2010" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2010 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE); # else - return ((png_charp) "libpng version 1.5.0beta24 - April 29, 2010\ + return ((png_charp) "libpng version 1.5.0beta24 - May 6, 2010\ Copyright (c) 1998-2010 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."); @@ -611,6 +623,7 @@ png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) png_bytep p; if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) return 0; + p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5; for (i = png_ptr->num_chunk_list; i; i--, p -= 5) if (!png_memcmp(chunk_name, p, 4)) @@ -627,6 +640,7 @@ png_reset_zstream(png_structp png_ptr) { if (png_ptr == NULL) return Z_STREAM_ERROR; + return (inflateReset(&png_ptr->zstream)); } #endif /* PNG_READ_SUPPORTED */ @@ -650,6 +664,7 @@ png_convert_size(size_t size) { if (size > (png_size_t)-1) PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + return ((png_size_t)size); } # endif /* PNG_SIZE_T */ @@ -739,16 +754,19 @@ png_check_cHRM_fixed(png_structp png_ptr, png_warning(png_ptr, "Invalid cHRM white point"); ret = 0; } + if (red_x > 100000L - red_y) { png_warning(png_ptr, "Invalid cHRM red point"); ret = 0; } + if (green_x > 100000L - green_y) { png_warning(png_ptr, "Invalid cHRM green point"); ret = 0; } + if (blue_x > 100000L - blue_y) { png_warning(png_ptr, "Invalid cHRM blue point"); @@ -793,6 +811,7 @@ png_check_IHDR(png_structp png_ptr, # ifdef PNG_SET_USER_LIMITS_SUPPORTED if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX) + # else if (width > PNG_USER_WIDTH_MAX) # endif diff --git a/png.h b/png.h index 896b3d8de..b6b2d04f6 100644 --- a/png.h +++ b/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.5.0beta24 - April 29, 2010 + * libpng version 1.5.0beta24 - May 6, 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.) @@ -11,7 +11,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.5.0beta24 - April 29, 2010: Glenn + * libpng versions 0.97, January 1998, through 1.5.0beta24 - May 6, 2010: Glenn * See also "Contributing Authors", below. * * Note about libpng version numbers: @@ -170,7 +170,7 @@ * * This code is released under the libpng license. * - * libpng versions 1.2.6, August 15, 2004, through 1.5.0beta24, April 29, 2010, are + * libpng versions 1.2.6, August 15, 2004, through 1.5.0beta24, May 6, 2010, are * Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are * distributed according to the same disclaimer and license as libpng-1.2.5 * with the following individual added to the list of Contributing Authors: @@ -282,7 +282,7 @@ * Y2K compliance in libpng: * ========================= * - * April 29, 2010 + * May 6, 2010 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. @@ -346,7 +346,7 @@ /* Version information for png.h - this should match the version in png.c */ #define PNG_LIBPNG_VER_STRING "1.5.0beta24" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.5.0beta24 - April 29, 2010\n" + " libpng version 1.5.0beta24 - May 6, 2010\n" #define PNG_LIBPNG_VER_SONUM 15 #define PNG_LIBPNG_VER_DLLNUM 15 diff --git a/pngconf.h b/pngconf.h index 07b041690..120b44012 100644 --- a/pngconf.h +++ b/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.5.0beta24 - April 29, 2010 + * libpng version 1.5.0beta24 - May 6, 2010 * * Copyright (c) 1998-2010 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/pngdebug.h b/pngdebug.h index 2d6b7c3a4..6f769ad8f 100644 --- a/pngdebug.h +++ b/pngdebug.h @@ -5,7 +5,7 @@ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * - * Last changed in libpng version 1.5.0 - April 29, 2010 + * Last changed in libpng version 1.5.0 - May 6, 2010 * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/pngerror.c b/pngerror.c index 4fddc7e43..105cd8c4e 100644 --- a/pngerror.c +++ b/pngerror.c @@ -1,7 +1,7 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -42,35 +42,38 @@ png_error(png_structp png_ptr, png_const_charp error_message) char msg[16]; if (png_ptr != NULL) { - if (png_ptr->flags& + if (png_ptr->flags& (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) - { - if (*error_message == PNG_LITERAL_SHARP) - { - /* Strip "#nnnn " from beginning of error message. */ - int offset; - for (offset = 1; offset<15; offset++) - if (error_message[offset] == ' ') + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') break; - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) - { - int i; - for (i = 0; i < offset - 1; i++) - msg[i] = error_message[i + 1]; - msg[i - 1] = '\0'; - error_message = msg; - } - else - error_message += offset; - } - else - { - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) - { - msg[0] = '0'; - msg[1] = '\0'; - error_message = msg; - } + + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + + else + error_message += offset; + } + + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } } } } @@ -168,6 +171,7 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp buffer[iout++] = png_digit[c & 0x0f]; buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; } + else { buffer[iout++] = (png_byte)c; @@ -176,6 +180,7 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp if (error_message == NULL) buffer[iout] = '\0'; + else { buffer[iout++] = ':'; @@ -193,6 +198,7 @@ png_chunk_error(png_structp png_ptr, png_const_charp error_message) char msg[18+PNG_MAX_ERROR_TEXT]; if (png_ptr == NULL) png_error(png_ptr, error_message); + else { png_format_buffer(png_ptr, msg, error_message); @@ -208,6 +214,7 @@ png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) char msg[18+PNG_MAX_ERROR_TEXT]; if (png_ptr == NULL) png_warning(png_ptr, warning_message); + else { png_format_buffer(png_ptr, msg, warning_message); @@ -223,6 +230,7 @@ png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) { if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) png_chunk_warning(png_ptr, error_message); + else png_chunk_error(png_ptr, error_message); } @@ -266,6 +274,7 @@ png_default_error(png_structp png_ptr, png_const_charp error_message) if (error_message[offset] == ' ') break; } + if ((offset > 1) && (offset < 15)) { error_number[offset - 1] = '\0'; @@ -273,6 +282,7 @@ png_default_error(png_structp png_ptr, png_const_charp error_message) error_number, error_message + offset + 1); fprintf(stderr, PNG_STRING_NEWLINE); } + else { fprintf(stderr, "libpng error: %s, offset=%d", @@ -300,11 +310,12 @@ png_longjmp(png_structp png_ptr, int val) if (png_ptr && png_ptr->longjmp_fn) { # ifdef USE_FAR_KEYWORD - { - jmp_buf png_jmpbuf; - png_memcpy(png_jmpbuf, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); - png_ptr->longjmp_fn(png_jmpbuf, val); - } + { + jmp_buf png_jmpbuf; + png_memcpy(png_jmpbuf, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); + png_ptr->longjmp_fn(png_jmpbuf, val); + } + # else png_ptr->longjmp_fn(png_ptr->png_jmpbuf, val); # endif @@ -335,6 +346,7 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message) if (warning_message[offset] == ' ') break; } + if ((offset > 1) && (offset < 15)) { warning_number[offset + 1] = '\0'; @@ -342,6 +354,7 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message) warning_number, warning_message + offset); fprintf(stderr, PNG_STRING_NEWLINE); } + else { fprintf(stderr, "libpng warning: %s", @@ -351,6 +364,7 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message) } else # endif + { fprintf(stderr, "libpng warning: %s", warning_message); fprintf(stderr, PNG_STRING_NEWLINE); @@ -373,6 +387,7 @@ png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, { if (png_ptr == NULL) return; + png_ptr->error_ptr = error_ptr; png_ptr->error_fn = error_fn; png_ptr->warning_fn = warning_fn; @@ -388,6 +403,7 @@ png_get_error_ptr(png_structp png_ptr) { if (png_ptr == NULL) return NULL; + return ((png_voidp)png_ptr->error_ptr); } diff --git a/pngget.c b/pngget.c index dd57e3cc3..6d489f220 100644 --- a/pngget.c +++ b/pngget.c @@ -1,7 +1,7 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.4.1 [April 29, 2010] + * Last changed in libpng 1.4.1 [May 6, 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.) @@ -343,11 +343,13 @@ png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, *res_x = info_ptr->x_pixels_per_unit; retval |= PNG_INFO_pHYs; } + if (res_y != NULL) { *res_y = info_ptr->y_pixels_per_unit; retval |= PNG_INFO_pHYs; } + if (unit_type != NULL) { *unit_type = (int)info_ptr->phys_unit_type; @@ -373,6 +375,7 @@ png_get_channels(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return(info_ptr->channels); + else return (0); } @@ -382,6 +385,7 @@ png_get_signature(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return(info_ptr->signature); + else return (NULL); } @@ -498,6 +502,7 @@ png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, *int_file_gamma = info_ptr->int_gamma; return (PNG_INFO_gAMA); } + return (0); } #endif @@ -515,6 +520,7 @@ png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) *file_srgb_intent = (int)info_ptr->srgb_intent; return (PNG_INFO_sRGB); } + return (0); } #endif @@ -539,6 +545,7 @@ png_get_iCCP(png_structp png_ptr, png_infop info_ptr, *compression_type = (int)info_ptr->iccp_compression; return (PNG_INFO_iCCP); } + return (0); } #endif @@ -553,6 +560,7 @@ png_get_sPLT(png_structp png_ptr, png_infop info_ptr, *spalettes = info_ptr->splt_palettes; return ((png_uint_32)info_ptr->splt_palettes_num); } + return (0); } #endif @@ -569,6 +577,7 @@ png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) *hist = info_ptr->hist; return (PNG_INFO_hIST); } + return (0); } #endif @@ -627,6 +636,7 @@ png_get_oFFs(png_structp png_ptr, png_infop info_ptr, *unit_type = (int)info_ptr->offset_unit_type; return (PNG_INFO_oFFs); } + return (0); } #endif @@ -652,6 +662,7 @@ png_get_pCAL(png_structp png_ptr, png_infop info_ptr, *params = info_ptr->pcal_params; return (PNG_INFO_pCAL); } + return (0); } #endif @@ -670,6 +681,7 @@ png_get_sCAL(png_structp png_ptr, png_infop info_ptr, *height = info_ptr->scal_pixel_height; return (PNG_INFO_sCAL); } + return(0); } #else @@ -686,6 +698,7 @@ png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, *height = info_ptr->scal_s_height; return (PNG_INFO_sCAL); } + return(0); } #endif @@ -722,6 +735,7 @@ png_get_pHYs(png_structp png_ptr, png_infop info_ptr, retval |= PNG_INFO_pHYs; } } + return (retval); } #endif @@ -740,6 +754,7 @@ png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, png_debug1(3, "num_palette = %d", *num_palette); return (PNG_INFO_PLTE); } + return (0); } @@ -755,6 +770,7 @@ png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) *sig_bit = &(info_ptr->sig_bit); return (PNG_INFO_sBIT); } + return (0); } #endif @@ -778,8 +794,10 @@ png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, return ((png_uint_32)info_ptr->num_text); } + if (num_text != NULL) *num_text = 0; + return(0); } #endif @@ -796,6 +814,7 @@ png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) *mod_time = &(info_ptr->mod_time); return (PNG_INFO_tIME); } + return (0); } #endif @@ -821,6 +840,7 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr, if (trans_color != NULL) *trans_color = &(info_ptr->trans_color); } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ { if (trans_color != NULL) @@ -832,12 +852,14 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr, if (trans_alpha != NULL) *trans_alpha = NULL; } + if (num_trans != NULL) { *num_trans = info_ptr->num_trans; retval |= PNG_INFO_tRNS; } } + return (retval); } #endif @@ -852,6 +874,7 @@ png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, *unknowns = info_ptr->unknown_chunks; return ((png_uint_32)info_ptr->unknown_chunks_num); } + return (0); } #endif diff --git a/pnginfo.h b/pnginfo.h index b2bb6f8ef..6016bc0d2 100644 --- a/pnginfo.h +++ b/pnginfo.h @@ -5,7 +5,7 @@ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * - * Last changed in libpng version 1.5.0 - April 29, 2010 + * Last changed in libpng version 1.5.0 - May 6, 2010 * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/pngmem.c b/pngmem.c index 89d905763..a63f5c4c4 100644 --- a/pngmem.c +++ b/pngmem.c @@ -1,7 +1,7 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -44,8 +44,10 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) if (type == PNG_STRUCT_INFO) size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) size = png_sizeof(png_struct); + else return (png_get_copyright(NULL)); @@ -57,11 +59,13 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) png_ptr->mem_ptr=mem_ptr; struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); } + else # endif /* PNG_USER_MEM_SUPPORTED */ struct_ptr = (png_voidp)farmalloc(size); if (struct_ptr != NULL) png_memset(struct_ptr, 0, size); + return (struct_ptr); } @@ -90,6 +94,7 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, (*(free_fn))(png_ptr, struct_ptr); return; } + # endif /* PNG_USER_MEM_SUPPORTED */ farfree (struct_ptr); } @@ -120,8 +125,10 @@ png_calloc(png_structp png_ptr, png_alloc_size_t size) png_voidp ret; ret = (png_malloc(png_ptr, size)); + if (ret != NULL) png_memset(ret,0,(png_size_t)size); + return (ret); } @@ -136,10 +143,13 @@ png_malloc(png_structp png_ptr, png_alloc_size_t size) # ifdef PNG_USER_MEM_SUPPORTED if (png_ptr->malloc_fn != NULL) ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out of memory"); + return (ret); } @@ -158,11 +168,13 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) png_warning(png_ptr, "Cannot Allocate > 64K"); ret = NULL; } + else # endif if (size != (size_t)size) ret = NULL; + else if (size == (png_uint_32)65536L) { if (png_ptr->offset_table == NULL) @@ -185,10 +197,13 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) if (png_ptr->zlib_window_bits > 14) num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else num_blocks++; @@ -201,6 +216,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) # ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */ + else png_warning(png_ptr, "Out Of Memory"); # endif @@ -213,6 +229,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Farmalloc didn't return normalized pointer"); + else png_warning(png_ptr, "Farmalloc didn't return normalized pointer"); @@ -229,6 +246,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) # ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */ + else png_warning(png_ptr, "Out Of memory"); # endif @@ -241,6 +259,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ } + for (i = 0; i < num_blocks; i++) { png_ptr->offset_table_ptr[i] = (png_bytep)hptr; @@ -258,6 +277,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) # ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out of Memory"); /* Note "o" and "M" */ + else png_warning(png_ptr, "Out of Memory"); # endif @@ -266,6 +286,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; } + else ret = farmalloc(size); @@ -274,6 +295,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) { if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */ + else png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */ } @@ -298,6 +320,7 @@ png_free(png_structp png_ptr, png_voidp ptr) (*(png_ptr->free_fn))(png_ptr, ptr); return; } + else png_free_default(png_ptr, ptr); } @@ -333,9 +356,7 @@ png_free_default(png_structp png_ptr, png_voidp ptr) } if (ptr != NULL) - { farfree(ptr); - } } #else /* Not the Borland DOS special memory handler */ @@ -362,8 +383,10 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) if (type == PNG_STRUCT_INFO) size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) size = png_sizeof(png_struct); + else return (NULL); @@ -374,8 +397,10 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) png_structp png_ptr = &dummy_struct; png_ptr->mem_ptr=mem_ptr; struct_ptr = (*(malloc_fn))(png_ptr, size); + if (struct_ptr != NULL) png_memset(struct_ptr, 0, size); + return (struct_ptr); } # endif /* PNG_USER_MEM_SUPPORTED */ @@ -389,6 +414,7 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) struct_ptr = (png_voidp)malloc(size); # endif # endif + if (struct_ptr != NULL) png_memset(struct_ptr, 0, size); @@ -424,11 +450,14 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, # endif /* PNG_USER_MEM_SUPPORTED */ # if defined(__TURBOC__) && !defined(__FLAT__) farfree(struct_ptr); + # else # if defined(_MSC_VER) && defined(MAXSEG_64K) hfree(struct_ptr); + # else free(struct_ptr); + # endif # endif } @@ -447,8 +476,10 @@ png_calloc(png_structp png_ptr, png_alloc_size_t size) png_voidp ret; ret = (png_malloc(png_ptr, size)); + if (ret != NULL) png_memset(ret,0,(png_size_t)size); + return (ret); } @@ -463,10 +494,13 @@ png_malloc(png_structp png_ptr, png_alloc_size_t size) if (png_ptr->malloc_fn != NULL) ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out of Memory"); + return (ret); } @@ -485,6 +519,7 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) # ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Cannot Allocate > 64K"); + else # endif return NULL; @@ -493,19 +528,25 @@ png_malloc_default(png_structp png_ptr, png_alloc_size_t size) /* Check for overflow */ # if defined(__TURBOC__) && !defined(__FLAT__) + if (size != (unsigned long)size) ret = NULL; + else ret = farmalloc(size); + # else # if defined(_MSC_VER) && defined(MAXSEG_64K) if (size != (unsigned long)size) ret = NULL; + else ret = halloc(size, 1); + # else if (size != (size_t)size) ret = NULL; + else ret = malloc((size_t)size); # endif @@ -534,6 +575,7 @@ png_free(png_structp png_ptr, png_voidp ptr) (*(png_ptr->free_fn))(png_ptr, ptr); return; } + else png_free_default(png_ptr, ptr); } @@ -547,11 +589,14 @@ png_free_default(png_structp png_ptr, png_voidp ptr) # if defined(__TURBOC__) && !defined(__FLAT__) farfree(ptr); + # else # if defined(_MSC_VER) && defined(MAXSEG_64K) hfree(ptr); + # else free(ptr); + # endif # endif } @@ -604,6 +649,7 @@ png_get_mem_ptr(png_structp png_ptr) { if (png_ptr == NULL) return (NULL); + return ((png_voidp)png_ptr->mem_ptr); } #endif /* PNG_USER_MEM_SUPPORTED */ diff --git a/pngpread.c b/pngpread.c index 4faa9c7cc..50e58e9a3 100644 --- a/pngpread.c +++ b/pngpread.c @@ -1,7 +1,7 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -134,6 +134,7 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr) if (num_checked < 4 && png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) png_error(png_ptr, "Not a PNG file"); + else png_error(png_ptr, "PNG file corrupted by ASCII conversion"); } @@ -585,6 +586,7 @@ png_push_crc_finish(png_structp png_ptr) if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) save_size = (png_size_t)png_ptr->skip_length; + else save_size = png_ptr->save_buffer_size; @@ -601,6 +603,7 @@ png_push_crc_finish(png_structp png_ptr) if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) save_size = (png_size_t)png_ptr->skip_length; + else save_size = png_ptr->current_buffer_size; @@ -639,6 +642,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) if (length < png_ptr->save_buffer_size) save_size = length; + else save_size = png_ptr->save_buffer_size; @@ -701,11 +705,13 @@ png_push_save_buffer(png_structp png_ptr) old_buffer = png_ptr->save_buffer; png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, (png_size_t)new_max); + if (png_ptr->save_buffer == NULL) { png_free(png_ptr, old_buffer); png_error(png_ptr, "Insufficient memory for save_buffer"); } + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); png_free(png_ptr, old_buffer); png_ptr->save_buffer_max = new_max; @@ -754,8 +760,10 @@ png_push_read_IDAT(png_structp png_ptr) if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) { png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) png_error(png_ptr, "Not enough compressed data"); + return; } @@ -773,6 +781,7 @@ png_push_read_IDAT(png_structp png_ptr) if ((png_uint_32)save_size != png_ptr->idat_size) png_error(png_ptr, "save_size overflowed in pngpread"); } + else save_size = png_ptr->save_buffer_size; @@ -802,6 +811,7 @@ png_push_read_IDAT(png_structp png_ptr) save_size = png_ptr->current_buffer_size; png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); @@ -871,6 +881,7 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, { if (png_ptr->zstream.avail_in) png_warning(png_ptr, "Too much data in IDAT chunks"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; break; } @@ -899,8 +910,8 @@ png_push_process_row(png_structp png_ptr) png_ptr->row_info.width); png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); @@ -1121,8 +1132,8 @@ png_read_push_finish_row(png_structp png_ptr) if (png_ptr->interlaced) { png_ptr->row_number = 0; - png_memset(png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + do { png_ptr->pass++; @@ -1138,17 +1149,17 @@ png_read_push_finish_row(png_structp png_ptr) break; png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; if (png_ptr->transformations & PNG_INTERLACE) break; png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); } @@ -1231,8 +1242,7 @@ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) if (text < key + png_ptr->current_text_size) text++; - text_ptr = (png_textp)png_malloc(png_ptr, - png_sizeof(png_text)); + text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text)); text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; text_ptr->key = key; text_ptr->itxt_length = 0; @@ -1258,10 +1268,10 @@ png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place zTXt"); - info_ptr = info_ptr; /* To quiet some compiler warnings */ - } + { + png_error(png_ptr, "Out of place zTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } #ifdef PNG_MAX_MALLOC_64K /* We can't handle zTXt chunks > 64K, since we don't have enough space @@ -1365,6 +1375,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) png_free(png_ptr, text); return; } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) { if (text == NULL) @@ -1383,6 +1394,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) *(text + text_size) = '\0'; } + else { png_charp tmp; @@ -1401,6 +1413,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; *(text + text_size) = '\0'; } + if (ret != Z_STREAM_END) { png_ptr->zstream.next_out = png_ptr->zbuf; @@ -1458,10 +1471,10 @@ png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place iTXt"); - info_ptr = info_ptr; /* To quiet some compiler warnings */ - } + { + png_error(png_ptr, "Out of place iTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } #ifdef PNG_MAX_MALLOC_64K png_ptr->skip_length = 0; /* This may not be necessary */ @@ -1501,6 +1514,7 @@ png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) png_ptr->current_text_left -= text_size; png_ptr->current_text_ptr += text_size; } + if (!(png_ptr->current_text_left)) { png_textp text_ptr; diff --git a/pngpriv.h b/pngpriv.h index ead53cf37..3ec0b1a67 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -1,7 +1,7 @@ /* pngpriv.h - private declarations for use inside libpng * - * libpng version 1.5.0beta24 - April 29, 2010 + * libpng version 1.5.0beta24 - May 6, 2010 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2010 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/pngread.c b/pngread.c index cabc3f539..8a4aa4314 100644 --- a/pngread.c +++ b/pngread.c @@ -1,7 +1,7 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -26,7 +26,7 @@ png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, #ifdef PNG_USER_MEM_SUPPORTED return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, NULL, NULL, NULL)); + warn_fn, NULL, NULL, NULL)); } /* Alternate create PNG structure for reading, and allocate any memory @@ -57,7 +57,7 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - malloc_fn, mem_ptr); + malloc_fn, mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif @@ -68,10 +68,12 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, #ifdef PNG_USER_LIMITS_SUPPORTED png_ptr->user_width_max = PNG_USER_WIDTH_MAX; png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; + # ifdef PNG_USER_CHUNK_CACHE_MAX /* Added at libpng-1.2.43 and 1.4.0 */ png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; # endif + # ifdef PNG_SET_USER_CHUNK_MALLOC_MAX /* Added at libpng-1.2.43 and 1.4.1 */ png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; @@ -102,23 +104,25 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, if (user_png_ver) { i = 0; + do { if (user_png_ver[i] != png_libpng_ver[i]) png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); - } - else - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } + + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) @@ -150,11 +154,12 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, { /* Initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, - png_ptr->zbuf_size); + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) png_cleanup_needed = 1; } + png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; @@ -163,12 +168,24 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, { switch (inflateInit(&png_ptr->zstream)) { - case Z_OK: /* Do nothing */ break; + case Z_OK: + break; /* Do nothing */ + case Z_MEM_ERROR: - case Z_STREAM_ERROR: png_warning(png_ptr, "zlib memory error"); - png_cleanup_needed = 1; break; - case Z_VERSION_ERROR: png_warning(png_ptr, "zlib version error"); - png_cleanup_needed = 1; break; + png_warning(png_ptr, "zlib memory error"); + png_cleanup_needed = 1; + break; + + case Z_STREAM_ERROR: + png_warning(png_ptr, "zlib stream error"); + png_cleanup_needed = 1; + break; + + case Z_VERSION_ERROR: + png_warning(png_ptr, "zlib version error"); + png_cleanup_needed = 1; + break; + default: png_warning(png_ptr, "Unknown zlib error"); png_cleanup_needed = 1; } @@ -233,9 +250,11 @@ png_read_info(png_structp png_ptr, png_infop info_ptr) if (num_checked < 4 && png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) png_error(png_ptr, "Not a PNG file"); + else png_error(png_ptr, "PNG file corrupted by ASCII conversion"); } + if (num_checked < 3) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; } @@ -309,33 +328,42 @@ png_read_info(png_structp png_ptr, png_infop info_ptr) if (!png_memcmp(chunk_name, png_IHDR, 4)) png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) png_handle_IEND(png_ptr, info_ptr, length); + #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED else if (png_handle_as_unknown(png_ptr, chunk_name)) { if (!png_memcmp(chunk_name, png_IDAT, 4)) png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(chunk_name, png_IDAT, 4)) { if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && !(png_ptr->mode & PNG_HAVE_PLTE)) png_error(png_ptr, "Missing PLTE before IDAT"); + break; } } #endif else if (!png_memcmp(chunk_name, png_PLTE, 4)) png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IDAT, 4)) { if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && !(png_ptr->mode & PNG_HAVE_PLTE)) png_error(png_ptr, "Missing PLTE before IDAT"); @@ -344,74 +372,92 @@ png_read_info(png_structp png_ptr, png_infop info_ptr) png_ptr->mode |= PNG_HAVE_IDAT; break; } + #ifdef PNG_READ_bKGD_SUPPORTED else if (!png_memcmp(chunk_name, png_bKGD, 4)) png_handle_bKGD(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_cHRM_SUPPORTED else if (!png_memcmp(chunk_name, png_cHRM, 4)) png_handle_cHRM(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (!png_memcmp(chunk_name, png_gAMA, 4)) png_handle_gAMA(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_hIST_SUPPORTED else if (!png_memcmp(chunk_name, png_hIST, 4)) png_handle_hIST(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_oFFs_SUPPORTED else if (!png_memcmp(chunk_name, png_oFFs, 4)) png_handle_oFFs(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_pCAL_SUPPORTED else if (!png_memcmp(chunk_name, png_pCAL, 4)) png_handle_pCAL(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sCAL_SUPPORTED else if (!png_memcmp(chunk_name, png_sCAL, 4)) png_handle_sCAL(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_pHYs_SUPPORTED else if (!png_memcmp(chunk_name, png_pHYs, 4)) png_handle_pHYs(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sBIT_SUPPORTED else if (!png_memcmp(chunk_name, png_sBIT, 4)) png_handle_sBIT(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sRGB_SUPPORTED else if (!png_memcmp(chunk_name, png_sRGB, 4)) png_handle_sRGB(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_iCCP_SUPPORTED else if (!png_memcmp(chunk_name, png_iCCP, 4)) png_handle_iCCP(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sPLT_SUPPORTED else if (!png_memcmp(chunk_name, png_sPLT, 4)) png_handle_sPLT(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_tEXt_SUPPORTED else if (!png_memcmp(chunk_name, png_tEXt, 4)) png_handle_tEXt(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_tIME_SUPPORTED else if (!png_memcmp(chunk_name, png_tIME, 4)) png_handle_tIME(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_tRNS_SUPPORTED else if (!png_memcmp(chunk_name, png_tRNS, 4)) png_handle_tRNS(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_zTXt_SUPPORTED else if (!png_memcmp(chunk_name, png_zTXt, 4)) png_handle_zTXt(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_iTXt_SUPPORTED else if (!png_memcmp(chunk_name, png_iTXt, 4)) png_handle_iTXt(png_ptr, info_ptr, length); #endif + else png_handle_unknown(png_ptr, info_ptr, length); } @@ -426,8 +472,10 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr) if (png_ptr == NULL) return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) png_read_start_row(png_ptr); + else png_warning(png_ptr, "Ignoring extra png_read_update_info() call;" @@ -449,6 +497,7 @@ png_start_read_image(png_structp png_ptr) if (png_ptr == NULL) return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) png_read_start_row(png_ptr); } @@ -472,6 +521,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) png_read_start_row(png_ptr); + if (png_ptr->row_number == 0 && png_ptr->pass == 0) { /* Check for transforms that have been set but were defined out */ @@ -479,27 +529,33 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) if (png_ptr->transformations & PNG_INVERT_MONO) png_warning(png_ptr, "PNG_READ_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_READ_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_READ_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_READ_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_READ_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_READ_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_READ_SWAP_SUPPORTED is not defined"); @@ -522,42 +578,50 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) return; } break; + case 1: if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) { if (dsp_row != NULL) png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); return; } break; + case 2: if ((png_ptr->row_number & 0x07) != 4) { if (dsp_row != NULL && (png_ptr->row_number & 4)) png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); return; } break; + case 3: if ((png_ptr->row_number & 3) || png_ptr->width < 3) { if (dsp_row != NULL) png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); return; } break; + case 4: if ((png_ptr->row_number & 3) != 2) { if (dsp_row != NULL && (png_ptr->row_number & 2)) png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); return; } @@ -567,11 +631,13 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) { if (dsp_row != NULL) png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); return; } break; + case 6: if (!(png_ptr->row_number & 1)) { @@ -590,6 +656,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + do { if (!(png_ptr->zstream.avail_in)) @@ -610,7 +677,9 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) (png_size_t)png_ptr->zstream.avail_in); png_ptr->idat_size -= png_ptr->zstream.avail_in; } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) { if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || @@ -620,6 +689,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; break; } + if (ret != Z_OK) png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : "Decompression error"); @@ -668,14 +738,17 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) if (dsp_row != NULL) png_combine_row(png_ptr, dsp_row, png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) png_combine_row(png_ptr, row, png_pass_mask[png_ptr->pass]); } + else #endif { if (row != NULL) png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) png_combine_row(png_ptr, dsp_row, 0xff); } @@ -723,6 +796,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row, if (png_ptr == NULL) return; + rp = row; dp = display_row; if (rp != NULL && dp != NULL) @@ -733,6 +807,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row, png_read_row(png_ptr, rptr, dptr); } + else if (rp != NULL) for (i = 0; i < num_rows; i++) { @@ -740,6 +815,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row, png_read_row(png_ptr, rptr, NULL); rp++; } + else if (dp != NULL) for (i = 0; i < num_rows; i++) { @@ -781,6 +857,7 @@ png_read_image(png_structp png_ptr, png_bytepp image) if (png_ptr->interlaced) png_error(png_ptr, "Cannot read interlaced image -- interlace handler disabled"); + pass = 1; #endif @@ -812,6 +889,7 @@ png_read_end(png_structp png_ptr, png_infop info_ptr) if (png_ptr == NULL) return; + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ do @@ -876,8 +954,10 @@ png_read_end(png_structp png_ptr, png_infop info_ptr) if (!png_memcmp(chunk_name, png_IHDR, 4)) png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) png_handle_IEND(png_ptr, info_ptr, length); + #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED else if (png_handle_as_unknown(png_ptr, chunk_name)) { @@ -891,6 +971,7 @@ png_read_end(png_structp png_ptr, png_infop info_ptr) png_ptr->mode |= PNG_HAVE_PLTE; } #endif + else if (!png_memcmp(chunk_name, png_IDAT, 4)) { /* Zero length IDATs are legal after the last IDAT has been @@ -898,78 +979,97 @@ png_read_end(png_structp png_ptr, png_infop info_ptr) */ if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) png_benign_error(png_ptr, "Too many IDATs found"); + png_crc_finish(png_ptr, length); } else if (!png_memcmp(chunk_name, png_PLTE, 4)) png_handle_PLTE(png_ptr, info_ptr, length); + #ifdef PNG_READ_bKGD_SUPPORTED else if (!png_memcmp(chunk_name, png_bKGD, 4)) png_handle_bKGD(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_cHRM_SUPPORTED else if (!png_memcmp(chunk_name, png_cHRM, 4)) png_handle_cHRM(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (!png_memcmp(chunk_name, png_gAMA, 4)) png_handle_gAMA(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_hIST_SUPPORTED else if (!png_memcmp(chunk_name, png_hIST, 4)) png_handle_hIST(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_oFFs_SUPPORTED else if (!png_memcmp(chunk_name, png_oFFs, 4)) png_handle_oFFs(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_pCAL_SUPPORTED else if (!png_memcmp(chunk_name, png_pCAL, 4)) png_handle_pCAL(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sCAL_SUPPORTED else if (!png_memcmp(chunk_name, png_sCAL, 4)) png_handle_sCAL(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_pHYs_SUPPORTED else if (!png_memcmp(chunk_name, png_pHYs, 4)) png_handle_pHYs(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sBIT_SUPPORTED else if (!png_memcmp(chunk_name, png_sBIT, 4)) png_handle_sBIT(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sRGB_SUPPORTED else if (!png_memcmp(chunk_name, png_sRGB, 4)) png_handle_sRGB(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_iCCP_SUPPORTED else if (!png_memcmp(chunk_name, png_iCCP, 4)) png_handle_iCCP(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_sPLT_SUPPORTED else if (!png_memcmp(chunk_name, png_sPLT, 4)) png_handle_sPLT(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_tEXt_SUPPORTED else if (!png_memcmp(chunk_name, png_tEXt, 4)) png_handle_tEXt(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_tIME_SUPPORTED else if (!png_memcmp(chunk_name, png_tIME, 4)) png_handle_tIME(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_tRNS_SUPPORTED else if (!png_memcmp(chunk_name, png_tRNS, 4)) png_handle_tRNS(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_zTXt_SUPPORTED else if (!png_memcmp(chunk_name, png_zTXt, 4)) png_handle_zTXt(png_ptr, info_ptr, length); #endif + #ifdef PNG_READ_iTXt_SUPPORTED else if (!png_memcmp(chunk_name, png_iTXt, 4)) png_handle_iTXt(png_ptr, info_ptr, length); #endif + else png_handle_unknown(png_ptr, info_ptr, length); } while (!(png_ptr->mode & PNG_HAVE_IEND)); @@ -1076,31 +1176,38 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_free(png_ptr, png_ptr->big_row_buf); png_free(png_ptr, png_ptr->prev_row); png_free(png_ptr, png_ptr->chunkdata); + #ifdef PNG_READ_QUANTIZE_SUPPORTED png_free(png_ptr, png_ptr->palette_lookup); png_free(png_ptr, png_ptr->quantize_index); #endif + #ifdef PNG_READ_GAMMA_SUPPORTED png_free(png_ptr, png_ptr->gamma_table); #endif + #ifdef PNG_READ_BACKGROUND_SUPPORTED png_free(png_ptr, png_ptr->gamma_from_1); png_free(png_ptr, png_ptr->gamma_to_1); #endif + if (png_ptr->free_me & PNG_FREE_PLTE) png_zfree(png_ptr, png_ptr->palette); png_ptr->free_me &= ~PNG_FREE_PLTE; + #if defined(PNG_tRNS_SUPPORTED) || \ defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->free_me & PNG_FREE_TRNS) png_free(png_ptr, png_ptr->trans_alpha); png_ptr->free_me &= ~PNG_FREE_TRNS; #endif + #ifdef PNG_READ_hIST_SUPPORTED if (png_ptr->free_me & PNG_FREE_HIST) png_free(png_ptr, png_ptr->hist); png_ptr->free_me &= ~PNG_FREE_HIST; #endif + #ifdef PNG_READ_GAMMA_SUPPORTED if (png_ptr->gamma_16_table != NULL) { @@ -1112,6 +1219,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, } png_free(png_ptr, png_ptr->gamma_16_table); } + #ifdef PNG_READ_BACKGROUND_SUPPORTED if (png_ptr->gamma_16_from_1 != NULL) { @@ -1135,11 +1243,13 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, } #endif #endif + #ifdef PNG_TIME_RFC1123_SUPPORTED png_free(png_ptr, png_ptr->time_buffer); #endif inflateEnd(&png_ptr->zstream); + #ifdef PNG_PROGRESSIVE_READ_SUPPORTED png_free(png_ptr, png_ptr->save_buffer); #endif @@ -1184,6 +1294,7 @@ png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) { if (png_ptr == NULL) return; + png_ptr->read_row_fn = read_row_fn; } diff --git a/pngrio.c b/pngrio.c index f7c515974..f99f67dd2 100644 --- a/pngrio.c +++ b/pngrio.c @@ -1,7 +1,7 @@ /* pngrio.c - functions for data input * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -35,6 +35,7 @@ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) if (png_ptr->read_data_fn != NULL) (*(png_ptr->read_data_fn))(png_ptr, data, length); + else png_error(png_ptr, "Call to NULL read function"); } @@ -53,6 +54,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) if (png_ptr == NULL) return; + /* fread() returns 0 on error, so it is OK to store this in a png_size_t * instead of an int, which is what fread() actually returns. */ @@ -79,19 +81,23 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) if (png_ptr == NULL) return; + /* Check if data really is near. If so, use usual code. */ n_data = (png_byte *)CVT_PTR_NOCHECK(data); io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) { check = fread(n_data, 1, length, io_ptr); } + else { png_byte buf[NEAR_BUF_SIZE]; png_size_t read, remaining, err; check = 0; remaining = length; + do { read = MIN(NEAR_BUF_SIZE, remaining); @@ -106,6 +112,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) } while (remaining != 0); } + if ((png_uint_32)check != (png_uint_32)length) png_error(png_ptr, "read Error"); } @@ -134,11 +141,13 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, { if (png_ptr == NULL) return; + png_ptr->io_ptr = io_ptr; #ifdef PNG_STDIO_SUPPORTED if (read_data_fn != NULL) png_ptr->read_data_fn = read_data_fn; + else png_ptr->read_data_fn = png_default_read_data; #else diff --git a/pngrtran.c b/pngrtran.c index 1d84eaca8..9fd6df5c3 100644 --- a/pngrtran.c +++ b/pngrtran.c @@ -1,7 +1,7 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -100,6 +100,7 @@ png_set_background(png_structp png_ptr, if (png_ptr == NULL) return; + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) { png_warning(png_ptr, "Application must supply a known background gamma"); @@ -124,6 +125,7 @@ png_set_strip_16(png_structp png_ptr) if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_16_TO_8; } #endif @@ -136,6 +138,7 @@ png_set_strip_alpha(png_structp png_ptr) if (png_ptr == NULL) return; + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; } #endif @@ -168,6 +171,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_QUANTIZE; if (!full_quantize) @@ -224,6 +228,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, done = 0; } } + if (done) break; } @@ -243,6 +248,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, do j--; while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + palette[i] = palette[j]; } } @@ -367,8 +373,10 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, t = (png_dsortp)png_malloc_warn(png_ptr, (png_uint_32)(png_sizeof(png_dsort))); + if (t == NULL) break; + t->next = hash[d]; t->left = (png_byte)i; t->right = (png_byte)j; @@ -419,6 +427,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, png_ptr->index_to_palette[j]) png_ptr->quantize_index[k] = png_ptr->index_to_palette[next_j]; + if ((int)png_ptr->quantize_index[k] == num_new_palette) png_ptr->quantize_index[k] = @@ -428,11 +437,13 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, png_ptr->index_to_palette[png_ptr->palette_to_index [num_new_palette]] = png_ptr->index_to_palette[j]; + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] = png_ptr->palette_to_index[num_new_palette]; png_ptr->index_to_palette[j] = (png_byte)num_new_palette; + png_ptr->palette_to_index[num_new_palette] = (png_byte)j; } @@ -490,6 +501,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * png_sizeof(png_byte))); + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); for (i = 0; i < num_palette; i++) @@ -661,8 +673,10 @@ png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, { int red_fixed = (int)((float)red*100000.0 + 0.5); int green_fixed = (int)((float)green*100000.0 + 0.5); + if (png_ptr == NULL) return; + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); } #endif @@ -696,6 +710,7 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, { png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; } #endif @@ -706,17 +721,20 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, red_int = 6968; /* .212671 * 32768 + .5 */ green_int = 23434; /* .715160 * 32768 + .5 */ } + else if (red + green < 100000L) { red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); } + else { png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); red_int = 6968; green_int = 23434; } + png_ptr->rgb_to_gray_red_coeff = red_int; png_ptr->rgb_to_gray_green_coeff = green_int; png_ptr->rgb_to_gray_blue_coeff = @@ -776,6 +794,7 @@ png_init_read_transformations(png_structp png_ptr) { png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; } + else if ((png_ptr->transformations & PNG_BACKGROUND) && !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && (png_ptr->transformations & PNG_GRAY_TO_RGB) && @@ -947,6 +966,7 @@ png_init_read_transformations(png_structp png_ptr) back.green = (png_byte)png_ptr->background.green; back.blue = (png_byte)png_ptr->background.blue; } + else { back.red = (png_byte)(pow( @@ -961,8 +981,10 @@ png_init_read_transformations(png_structp png_ptr) back_1.red = (png_byte)(pow( (double)png_ptr->background.red/255.0, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( (double)png_ptr->background.green/255.0, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( (double)png_ptr->background.blue/255.0, g) * 255.0 + .5); } @@ -1007,6 +1029,7 @@ png_init_read_transformations(png_structp png_ptr) png_ptr->transformations &= ~PNG_GAMMA; png_ptr->transformations |= PNG_STRIP_ALPHA; } + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ else /* color_type != PNG_COLOR_TYPE_PALETTE */ @@ -1036,6 +1059,7 @@ png_init_read_transformations(png_structp png_ptr) png_ptr->background_1.gray = (png_uint_16)(pow( (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( (double)png_ptr->background.gray / m, gs) * m + .5); @@ -1046,22 +1070,29 @@ png_init_read_transformations(png_structp png_ptr) /* RGB or RGBA with color background */ png_ptr->background_1.red = (png_uint_16)(pow( (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( (double)png_ptr->background.blue / m, gs) * m + .5); } + else { /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ png_ptr->background_1.red = png_ptr->background_1.green = png_ptr->background_1.blue = png_ptr->background_1.gray; + png_ptr->background.red = png_ptr->background.green = png_ptr->background.blue = png_ptr->background.gray; } @@ -1111,13 +1142,16 @@ png_init_read_transformations(png_structp png_ptr) { palette[i] = back; } + else if (png_ptr->trans_alpha[i] != 0xff) { /* The png_composite() macro is defined in png.h */ png_composite(palette[i].red, palette[i].red, png_ptr->trans_alpha[i], back.red); + png_composite(palette[i].green, palette[i].green, png_ptr->trans_alpha[i], back.green); + png_composite(palette[i].blue, palette[i].blue, png_ptr->trans_alpha[i], back.blue); } @@ -1141,10 +1175,13 @@ png_init_read_transformations(png_structp png_ptr) if (sr < 0 || sr > 8) sr = 0; + if (sg < 0 || sg > 8) sg = 0; + if (sb < 0 || sb > 8) sb = 0; + for (i = 0; i < istop; i++) { png_ptr->palette[i].red >>= sr; @@ -1178,8 +1215,10 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS)) info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; info_ptr->num_trans = 0; } @@ -1192,6 +1231,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) } if (info_ptr->bit_depth < 8) info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; } } @@ -1252,8 +1292,10 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) info_ptr->channels = 3; + else info_ptr->channels = 1; @@ -1284,6 +1326,7 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED) { if (info_ptr->bit_depth < png_ptr->user_transform_depth) info_ptr->bit_depth = png_ptr->user_transform_depth; + if (info_ptr->channels < png_ptr->user_transform_channels) info_ptr->channels = png_ptr->user_transform_channels; } @@ -1350,6 +1393,7 @@ png_do_read_transformations(png_structp png_ptr) png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, &(png_ptr->trans_color)); else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, NULL); } @@ -1366,14 +1410,16 @@ png_do_read_transformations(png_structp png_ptr) if (png_ptr->transformations & PNG_RGB_TO_GRAY) { int rgb_error = - png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1); + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1); + if (rgb_error) { png_ptr->rgb_to_gray_status=1; if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == PNG_RGB_TO_GRAY_WARN) png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == PNG_RGB_TO_GRAY_ERR) png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); @@ -1460,6 +1506,7 @@ png_do_read_transformations(png_structp png_ptr) { png_do_quantize((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr->palette_lookup, png_ptr->quantize_index); + if (png_ptr->row_info.rowbytes == (png_uint_32)0) png_error(png_ptr, "png_do_quantize returned rowbytes=0"); } @@ -1536,11 +1583,13 @@ png_do_read_transformations(png_structp png_ptr) #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED if (png_ptr->user_transform_depth) png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if (png_ptr->user_transform_channels) png_ptr->row_info.channels = png_ptr->user_transform_channels; #endif 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_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->row_info.width); } @@ -1575,11 +1624,13 @@ png_do_unpack(png_row_infop row_info, png_bytep row) for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) { shift = 0; sp--; } + else shift++; @@ -1597,11 +1648,13 @@ png_do_unpack(png_row_infop row_info, png_bytep row) for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) { shift = 0; sp--; } + else shift += 2; @@ -1618,11 +1671,13 @@ png_do_unpack(png_row_infop row_info, png_bytep row) for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) { shift = 0; sp--; } + else shift = 4; @@ -1664,10 +1719,12 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) shift[channels++] = row_info->bit_depth - sig_bits->green; shift[channels++] = row_info->bit_depth - sig_bits->blue; } + else { shift[channels++] = row_info->bit_depth - sig_bits->gray; } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) { shift[channels++] = row_info->bit_depth - sig_bits->alpha; @@ -1677,6 +1734,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) { if (shift[c] <= 0) shift[c] = 0; + else value = 1; } @@ -2023,6 +2081,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, row_info->pixel_depth = 16; row_info->rowbytes = row_width * 2; } + else { /* This changes the data from G to XG */ @@ -2038,6 +2097,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, row_info->rowbytes = row_width * 2; } } + else if (row_info->bit_depth == 16) { if (flags & PNG_FLAG_FILLER_AFTER) @@ -2058,6 +2118,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, row_info->pixel_depth = 32; row_info->rowbytes = row_width * 4; } + else { /* This changes the data from GG to XXGG */ @@ -2097,6 +2158,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, row_info->pixel_depth = 32; row_info->rowbytes = row_width * 4; } + else { /* This changes the data from RGB to XRGB */ @@ -2114,6 +2176,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, row_info->rowbytes = row_width * 4; } } + else if (row_info->bit_depth == 16) { if (flags & PNG_FLAG_FILLER_AFTER) @@ -2138,6 +2201,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, row_info->pixel_depth = 64; row_info->rowbytes = row_width * 8; } + else { /* This changes the data from RRGGBB to XXRRGGBB */ @@ -2154,6 +2218,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, *(--dp) = hi_filler; *(--dp) = lo_filler; } + row_info->channels = 4; row_info->pixel_depth = 64; row_info->rowbytes = row_width * 8; @@ -2190,6 +2255,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) *(dp--) = *(sp--); } } + else { /* This changes GG to RRGGBB */ @@ -2206,6 +2272,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) } } } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (row_info->bit_depth == 8) @@ -2221,6 +2288,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) *(dp--) = *(sp--); } } + else { /* This changes GGAA to RRGGBBAA */ @@ -2303,12 +2371,14 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) png_byte red = png_ptr->gamma_to_1[*(sp++)]; png_byte green = png_ptr->gamma_to_1[*(sp++)]; png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) { rgb_error |= 1; *(dp++) = png_ptr->gamma_from_1[ (rc*red + gc*green + bc*blue)>>15]; } + else *(dp++) = *(sp - 1); } @@ -2323,11 +2393,13 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) png_byte red = *(sp++); png_byte green = *(sp++); png_byte blue = *(sp++); + if (red != green || red != blue) { rgb_error |= 1; *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); } + else *(dp++) = *(sp - 1); } @@ -2352,6 +2424,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) if (red == green && red == blue) w = red; + else { png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) @@ -2387,6 +2460,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) if (red != green || red != blue) rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); *(dp++) = (png_byte)((gray16>>8) & 0xff); *(dp++) = (png_byte)(gray16 & 0xff); @@ -2408,10 +2482,13 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) png_byte red = png_ptr->gamma_to_1[*(sp++)]; png_byte green = png_ptr->gamma_to_1[*(sp++)]; png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ } } @@ -2427,6 +2504,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) png_byte blue = *(sp++); if (red != green || red != blue) rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); *(dp++) = *(sp++); /* alpha */ } @@ -2450,19 +2528,25 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) if (red == green && red == blue) w = red; + else { png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; } @@ -2483,8 +2567,10 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) red = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; green = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; blue = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + if (red != green || red != blue) rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); *(dp++) = (png_byte)((gray16>>8) & 0xff); *(dp++) = (png_byte)(gray16 & 0xff); @@ -2604,11 +2690,13 @@ png_do_background(png_row_infop row_info, png_bytep row, *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); *sp |= (png_byte)(background->gray << shift); } + if (!shift) { shift = 7; sp++; } + else shift--; } @@ -2630,6 +2718,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); *sp |= (png_byte)(background->gray << shift); } + else { png_byte p = (png_byte)((*sp >> shift) & 0x03); @@ -2638,15 +2727,18 @@ png_do_background(png_row_infop row_info, png_bytep row, *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); *sp |= (png_byte)(g << shift); } + if (!shift) { shift = 6; sp++; } + else shift -= 2; } } + else #endif { @@ -2660,11 +2752,13 @@ png_do_background(png_row_infop row_info, png_bytep row, *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); *sp |= (png_byte)(background->gray << shift); } + if (!shift) { shift = 6; sp++; } + else shift -= 2; } @@ -2687,6 +2781,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); *sp |= (png_byte)(background->gray << shift); } + else { png_byte p = (png_byte)((*sp >> shift) & 0x0f); @@ -2695,15 +2790,18 @@ png_do_background(png_row_infop row_info, png_bytep row, *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); *sp |= (png_byte)(g << shift); } + if (!shift) { shift = 4; sp++; } + else shift -= 4; } } + else #endif { @@ -2717,11 +2815,13 @@ png_do_background(png_row_infop row_info, png_bytep row, *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); *sp |= (png_byte)(background->gray << shift); } + if (!shift) { shift = 4; sp++; } + else shift -= 4; } @@ -2768,12 +2868,14 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 v; v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_color->gray) { /* Background is already in screen gamma */ *sp = (png_byte)((background->gray >> 8) & 0xff); *(sp + 1) = (png_byte)(background->gray & 0xff); } + else { v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; @@ -2791,6 +2893,7 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 v; v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_color->gray) { *sp = (png_byte)((background->gray >> 8) & 0xff); @@ -2822,6 +2925,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *(sp + 1) = (png_byte)background->green; *(sp + 2) = (png_byte)background->blue; } + else { *sp = gamma_table[*sp]; @@ -2856,10 +2960,13 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++, sp += 6) { png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); + if (r == trans_color->red && g == trans_color->green && b == trans_color->blue) { @@ -2871,20 +2978,24 @@ png_do_background(png_row_infop row_info, png_bytep row, *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); *(sp + 5) = (png_byte)(background->blue & 0xff); } + else { png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; *(sp + 2) = (png_byte)((v >> 8) & 0xff); *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; *(sp + 4) = (png_byte)((v >> 8) & 0xff); *(sp + 5) = (png_byte)(v & 0xff); } } } + else #endif { @@ -2892,8 +3003,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++, sp += 6) { png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); @@ -2935,6 +3048,7 @@ png_do_background(png_row_infop row_info, png_bytep row, /* Background is already in screen gamma */ *dp = (png_byte)background->gray; } + else { png_byte v, w; @@ -2991,6 +3105,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *dp = (png_byte)((v >> 8) & 0xff); *(dp + 1) = (png_byte)(v & 0xff); } + #ifdef PNG_READ_GAMMA_SUPPORTED else if (a == 0) #else @@ -3001,6 +3116,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *dp = (png_byte)((background->gray >> 8) & 0xff); *(dp + 1) = (png_byte)(background->gray & 0xff); } + #ifdef PNG_READ_GAMMA_SUPPORTED else { @@ -3024,6 +3140,7 @@ png_do_background(png_row_infop row_info, png_bytep row, { png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + *(sp + 3)); + if (a == (png_uint_16)0xffff) png_memcpy(dp, sp, 2); @@ -3036,6 +3153,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *dp = (png_byte)((background->gray >> 8) & 0xff); *(dp + 1) = (png_byte)(background->gray & 0xff); } + #ifdef PNG_READ_GAMMA_SUPPORTED else { @@ -3073,6 +3191,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *(dp + 1) = gamma_table[*(sp + 1)]; *(dp + 2) = gamma_table[*(sp + 2)]; } + else if (a == 0) { /* Background is already in screen gamma */ @@ -3080,6 +3199,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *(dp + 1) = (png_byte)background->green; *(dp + 2) = (png_byte)background->blue; } + else { png_byte v, w; @@ -3087,9 +3207,11 @@ png_do_background(png_row_infop row_info, png_bytep row, v = gamma_to_1[*sp]; png_composite(w, v, a, background_1->red); *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; png_composite(w, v, a, background_1->green); *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; png_composite(w, v, a, background_1->blue); *(dp + 2) = gamma_from_1[w]; @@ -3111,17 +3233,21 @@ png_do_background(png_row_infop row_info, png_bytep row, *(dp + 1) = *(sp + 1); *(dp + 2) = *(sp + 2); } + else if (a == 0) { *dp = (png_byte)background->red; *(dp + 1) = (png_byte)background->green; *(dp + 2) = (png_byte)background->blue; } + else { png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, background->green); + png_composite(*(dp + 2), *(sp + 2), a, background->blue); } @@ -3140,6 +3266,7 @@ png_do_background(png_row_infop row_info, png_bytep row, { png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) { png_uint_16 v; @@ -3147,13 +3274,16 @@ png_do_background(png_row_infop row_info, png_bytep row, v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; *dp = (png_byte)((v >> 8) & 0xff); *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; *(dp + 2) = (png_byte)((v >> 8) & 0xff); *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; *(dp + 4) = (png_byte)((v >> 8) & 0xff); *(dp + 5) = (png_byte)(v & 0xff); } + else if (a == 0) { /* Background is already in screen gamma */ @@ -3164,30 +3294,35 @@ png_do_background(png_row_infop row_info, png_bytep row, *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); *(dp + 5) = (png_byte)(background->blue & 0xff); } + else { png_uint_16 v, w, x; v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; png_composite_16(w, v, a, background_1->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; *dp = (png_byte)((x >> 8) & 0xff); *(dp + 1) = (png_byte)(x & 0xff); v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; png_composite_16(w, v, a, background_1->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; *(dp + 2) = (png_byte)((x >> 8) & 0xff); *(dp + 3) = (png_byte)(x & 0xff); v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; png_composite_16(w, v, a, background_1->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; *(dp + 4) = (png_byte)((x >> 8) & 0xff); *(dp + 5) = (png_byte)(x & 0xff); } } } + else #endif { @@ -3197,10 +3332,12 @@ png_do_background(png_row_infop row_info, png_bytep row, { png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) { png_memcpy(dp, sp, 6); } + else if (a == 0) { *dp = (png_byte)((background->red >> 8) & 0xff); @@ -3210,6 +3347,7 @@ png_do_background(png_row_infop row_info, png_bytep row, *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); *(dp + 5) = (png_byte)(background->blue & 0xff); } + else { png_uint_16 v; @@ -3223,9 +3361,11 @@ png_do_background(png_row_infop row_info, png_bytep row, png_composite_16(v, r, a, background->red); *dp = (png_byte)((v >> 8) & 0xff); *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); *(dp + 2) = (png_byte)((v >> 8) & 0xff); *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); *(dp + 4) = (png_byte)((v >> 8) & 0xff); *(dp + 5) = (png_byte)(v & 0xff); @@ -3267,8 +3407,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_gamma"); - if ( - ((row_info->bit_depth <= 8 && gamma_table != NULL) || + if (((row_info->bit_depth <= 8 && gamma_table != NULL) || (row_info->bit_depth == 16 && gamma_16_table != NULL))) { switch (row_info->color_type) @@ -3288,6 +3427,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, sp++; } } + else /* if (row_info->bit_depth == 16) */ { sp = row; @@ -3333,6 +3473,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, sp++; } } + else /* if (row_info->bit_depth == 16) */ { sp = row; @@ -3368,6 +3509,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, sp += 2; } } + else /* if (row_info->bit_depth == 16) */ { sp = row; @@ -3460,8 +3602,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_expand_palette"); - if ( - row_info->color_type == PNG_COLOR_TYPE_PALETTE) + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) { if (row_info->bit_depth < 8) { @@ -3485,6 +3626,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, shift = 0; sp--; } + else shift++; @@ -3507,6 +3649,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, shift = 0; sp--; } + else shift += 2; @@ -3529,6 +3672,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, shift = 0; sp--; } + else shift += 4; @@ -3541,6 +3685,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, row_info->pixel_depth = 8; row_info->rowbytes = row_width; } + switch (row_info->bit_depth) { case 8: @@ -3569,6 +3714,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, row_info->color_type = 6; row_info->channels = 4; } + else { sp = row + (png_size_t)row_width - 1; @@ -3636,6 +3782,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, shift = 0; sp--; } + else shift++; @@ -3660,6 +3807,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, shift = 0; sp--; } + else shift += 2; @@ -3683,6 +3831,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, shift = 0; sp--; } + else shift = 4; @@ -3704,12 +3853,15 @@ png_do_expand(png_row_infop row_info, png_bytep row, gray = gray & 0xff; sp = row + (png_size_t)row_width - 1; dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) { if (*sp == gray) *dp-- = 0; + else *dp-- = 0xff; + *dp-- = *sp--; } } @@ -3727,11 +3879,13 @@ png_do_expand(png_row_infop row_info, png_bytep row, *dp-- = 0; *dp-- = 0; } + else { *dp-- = 0xff; *dp-- = 0xff; } + *dp-- = *sp--; *dp-- = *sp--; } @@ -3757,8 +3911,10 @@ png_do_expand(png_row_infop row_info, png_bytep row, { if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) *dp-- = 0; + else *dp-- = 0xff; + *dp-- = *sp--; *dp-- = *sp--; *dp-- = *sp--; @@ -3786,11 +3942,13 @@ png_do_expand(png_row_infop row_info, png_bytep row, *dp-- = 0; *dp-- = 0; } + else { *dp-- = 0xff; *dp-- = 0xff; } + *dp-- = *sp--; *dp-- = *sp--; *dp-- = *sp--; @@ -3850,11 +4008,13 @@ png_do_quantize(png_row_infop row_info, png_bytep row, *dp++ = palette_lookup[p]; } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; row_info->channels = 1; row_info->pixel_depth = row_info->bit_depth; row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && palette_lookup != NULL && row_info->bit_depth == 8) { @@ -3879,15 +4039,18 @@ png_do_quantize(png_row_infop row_info, png_bytep row, *dp++ = palette_lookup[p]; } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; row_info->channels = 1; row_info->pixel_depth = row_info->bit_depth; row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && quantize_lookup && row_info->bit_depth == 8) { sp = row; + for (i = 0; i < row_width; i++, sp++) { *sp = quantize_lookup[*sp]; @@ -4041,6 +4204,7 @@ png_build_gamma_table(png_structp png_ptr, png_byte bit_depth) if (png_ptr->screen_gamma > .000001) g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else g = 1.0; @@ -4073,6 +4237,7 @@ png_build_gamma_table(png_structp png_ptr, png_byte bit_depth) last++; } } + while (last < ((png_uint_32)num << 8)) { png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] @@ -4115,6 +4280,7 @@ png_build_gamma_table(png_structp png_ptr, png_byte bit_depth) ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) { png_ptr->gamma_16_to_1[i][j] = @@ -4167,6 +4333,7 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) { int bytes_per_pixel; png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) { png_bytep rp; diff --git a/pngrutil.c b/pngrutil.c index 5be9ad91c..7d519119a 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.4.1 [April 29, 2010] + * Last changed in libpng 1.4.1 [May 6, 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.) @@ -142,6 +142,7 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip) { png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); } + if (i) { png_crc_read(png_ptr, png_ptr->zbuf, i); @@ -156,11 +157,13 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip) { png_chunk_warning(png_ptr, "CRC error"); } + else { png_chunk_benign_error(png_ptr, "CRC error"); return (0); } + return (1); } @@ -183,6 +186,7 @@ png_crc_error(png_structp png_ptr) (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) need_crc = 0; } + else /* critical */ { if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) @@ -202,6 +206,7 @@ png_crc_error(png_structp png_ptr) crc = png_get_uint_32(crc_bytes); return ((int)(crc != png_ptr->crc)); } + else return (0); } @@ -276,9 +281,11 @@ png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size, case Z_BUF_ERROR: msg = "Buffer error in compressed datastream in %s chunk"; break; + case Z_DATA_ERROR: msg = "Data error in compressed datastream in %s chunk"; break; + default: msg = "Incomplete compressed datastream in %s chunk"; break; @@ -604,6 +611,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_chunk_benign_error(png_ptr, "CRC error"); } + else { png_chunk_warning(png_ptr, "CRC error"); @@ -630,6 +638,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); png_ptr->num_trans = (png_uint_16)num; } + if (info_ptr->num_trans > (png_uint_16)num) { png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); @@ -657,6 +666,7 @@ png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_warning(png_ptr, "Incorrect IEND chunk length"); } + png_crc_finish(png_ptr, length); info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ @@ -711,11 +721,11 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) igamma = (png_fixed_point)png_get_uint_32(buf); /* Check for zero gamma */ if (igamma == 0) - { - png_warning(png_ptr, - "Ignoring gAMA chunk with gamma=0"); - return; - } + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } #ifdef PNG_READ_sRGB_SUPPORTED if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) @@ -756,17 +766,20 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sBIT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sBIT after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (png_ptr->mode & PNG_HAVE_PLTE) { /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Out of place sBIT chunk"); } + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) { png_warning(png_ptr, "Duplicate sBIT chunk"); @@ -776,6 +789,7 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) truelen = 3; + else truelen = (png_size_t)png_ptr->channels; @@ -787,6 +801,7 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) return; @@ -797,6 +812,7 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->sig_bit.blue = buf[2]; png_ptr->sig_bit.alpha = buf[3]; } + else { png_ptr->sig_bit.gray = buf[0]; @@ -805,6 +821,7 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->sig_bit.blue = buf[0]; png_ptr->sig_bit.alpha = buf[1]; } + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); } #endif @@ -826,12 +843,14 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before cHRM"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid cHRM after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (png_ptr->mode & PNG_HAVE_PLTE) /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Missing PLTE before cHRM"); @@ -891,7 +910,7 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #ifdef PNG_READ_sRGB_SUPPORTED if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) - { + { if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || @@ -900,27 +919,27 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); #ifdef PNG_CONSOLE_IO_SUPPORTED #ifdef PNG_FLOATING_POINT_SUPPORTED - fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", - white_x, white_y, red_x, red_y); - fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", - green_x, green_y, blue_x, blue_y); + fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); #else - fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", - (long)int_x_white, (long)int_y_white, - (long)int_x_red, (long)int_y_red); - fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", - (long)int_x_green, (long)int_y_green, - (long)int_x_blue, (long)int_y_blue); + fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + (long)int_x_white, (long)int_y_white, + (long)int_x_red, (long)int_y_red); + fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + (long)int_x_green, (long)int_y_green, + (long)int_x_blue, (long)int_y_blue); #endif #endif /* PNG_CONSOLE_IO_SUPPORTED */ - } - return; } + return; + } #endif /* PNG_READ_sRGB_SUPPORTED */ #ifdef PNG_FLOATING_POINT_SUPPORTED @@ -946,12 +965,14 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sRGB"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sRGB after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (png_ptr->mode & PNG_HAVE_PLTE) /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Out of place sRGB chunk"); @@ -971,6 +992,7 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 1); + if (png_crc_finish(png_ptr, 0)) return; @@ -1022,10 +1044,10 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - } + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } #endif /* PNG_FIXED_POINT_SUPPORTED */ #endif /* PNG_READ_cHRM_SUPPORTED */ @@ -1049,12 +1071,14 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before iCCP"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid iCCP after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (png_ptr->mode & PNG_HAVE_PLTE) /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Out of place iCCP chunk"); @@ -1200,6 +1224,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sPLT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sPLT after IDAT"); @@ -1233,6 +1258,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++) /* Empty loop to find end of name */ ; + ++entry_start; /* A sample depth should follow the separator, and we should be on it */ @@ -1264,8 +1290,10 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_warning(png_ptr, "sPLT chunk too long"); return; } + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + if (new_palette.entries == NULL) { png_warning(png_ptr, "sPLT chunk requires too much memory"); @@ -1284,6 +1312,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) pp->blue = *entry_start++; pp->alpha = *entry_start++; } + else { pp->red = png_get_uint_16(entry_start); entry_start += 2; @@ -1291,6 +1320,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) pp->blue = png_get_uint_16(entry_start); entry_start += 2; pp->alpha = png_get_uint_16(entry_start); entry_start += 2; } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; } #else @@ -1305,6 +1335,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) pp[i].blue = *entry_start++; pp[i].alpha = *entry_start++; } + else { pp[i].red = png_get_uint_16(entry_start); entry_start += 2; @@ -1312,6 +1343,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; } #endif @@ -1343,6 +1375,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) { png_warning(png_ptr, "Duplicate tRNS chunk"); @@ -1365,6 +1398,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->num_trans = 1; png_ptr->trans_color.gray = png_get_uint_16(buf); } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { png_byte buf[6]; @@ -1381,6 +1415,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->trans_color.green = png_get_uint_16(buf + 2); png_ptr->trans_color.blue = png_get_uint_16(buf + 4); } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { if (!(png_ptr->mode & PNG_HAVE_PLTE)) @@ -1404,6 +1439,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_read(png_ptr, readbuf, (png_size_t)length); png_ptr->num_trans = (png_uint_16)length; } + else { png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); @@ -1433,12 +1469,14 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before bKGD"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid bKGD after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && !(png_ptr->mode & PNG_HAVE_PLTE)) { @@ -1446,6 +1484,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) { png_warning(png_ptr, "Duplicate bKGD chunk"); @@ -1455,8 +1494,10 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) truelen = 1; + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) truelen = 6; + else truelen = 2; @@ -1468,6 +1509,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) return; @@ -1486,14 +1528,18 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_warning(png_ptr, "Incorrect bKGD chunk index value"); return; } + png_ptr->background.red = (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; } } + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ { png_ptr->background.red = @@ -1501,6 +1547,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->background.blue = png_ptr->background.gray = png_get_uint_16(buf); } + else { png_ptr->background.red = png_get_uint_16(buf); @@ -1523,18 +1570,21 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before hIST"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid hIST after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) { png_warning(png_ptr, "Missing PLTE before hIST"); png_crc_finish(png_ptr, length); return; } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) { png_warning(png_ptr, "Duplicate hIST chunk"); @@ -1578,12 +1628,14 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before pHYs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid pHYs after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) { png_warning(png_ptr, "Duplicate pHYs chunk"); @@ -1599,6 +1651,7 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) return; @@ -1621,12 +1674,14 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before oFFs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid oFFs after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) { png_warning(png_ptr, "Duplicate oFFs chunk"); @@ -1642,6 +1697,7 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) return; @@ -1668,12 +1724,14 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before pCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid pCAL after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) { png_warning(png_ptr, "Duplicate pCAL chunk"); @@ -1685,11 +1743,13 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) length + 1); png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) { png_warning(png_ptr, "No memory for pCAL purpose"); return; } + slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); @@ -1740,6 +1800,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } + else if (type >= PNG_EQUATION_LAST) { png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); @@ -1808,12 +1869,14 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sCAL after IDAT"); png_crc_finish(png_ptr, length); return; } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) { png_warning(png_ptr, "Duplicate sCAL chunk"); @@ -1824,11 +1887,13 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", length + 1); png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) { png_warning(png_ptr, "Out of memory while processing sCAL chunk"); return; } + slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); @@ -1853,17 +1918,20 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #else #ifdef PNG_FIXED_POINT_SUPPORTED swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) { png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); return; } + png_memcpy(swidth, ep, png_strlen(ep)); #endif #endif for (ep = png_ptr->chunkdata; *ep; ep++) /* Empty loop */ ; + ep++; if (png_ptr->chunkdata + slength < ep) @@ -1880,19 +1948,23 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #ifdef PNG_FLOATING_POINT_SUPPORTED height = png_strtod(png_ptr, ep, &vp); + if (*vp) { png_warning(png_ptr, "malformed height string in sCAL chunk"); return; } + #else #ifdef PNG_FIXED_POINT_SUPPORTED sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (sheight == NULL) { png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); return; } + png_memcpy(sheight, ep, png_strlen(ep)); #endif #endif @@ -1942,6 +2014,7 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Out of place tIME chunk"); + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) { png_warning(png_ptr, "Duplicate tIME chunk"); @@ -1960,6 +2033,7 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 7); + if (png_crc_finish(png_ptr, 0)) return; @@ -1996,6 +2070,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + if (--png_ptr->user_chunk_cache_max == 1) { png_warning(png_ptr, "No space in chunk cache for tEXt"); @@ -2050,6 +2125,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) text_ptr = (png_textp)png_malloc_warn(png_ptr, png_sizeof(png_text)); + if (text_ptr == NULL) { png_warning(png_ptr, "Not enough memory to process text chunk"); @@ -2057,6 +2133,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; text_ptr->key = key; text_ptr->lang = NULL; @@ -2070,6 +2147,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; png_free(png_ptr, text_ptr); + if (ret) png_warning(png_ptr, "Insufficient memory to process text chunk"); } @@ -2096,6 +2174,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + if (--png_ptr->user_chunk_cache_max == 1) { png_warning(png_ptr, "No space in chunk cache for zTXt"); @@ -2130,8 +2209,10 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_warning(png_ptr, "Out of memory processing zTXt chunk"); return; } + slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) { png_free(png_ptr, png_ptr->chunkdata); @@ -2152,6 +2233,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } + else { comp_type = *(++text); @@ -2162,6 +2244,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } text++; /* Skip the compression_method byte */ } + prefix_len = text - png_ptr->chunkdata; png_decompress_chunk(png_ptr, comp_type, @@ -2169,6 +2252,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) text_ptr = (png_textp)png_malloc_warn(png_ptr, png_sizeof(png_text)); + if (text_ptr == NULL) { png_warning(png_ptr, "Not enough memory to process zTXt chunk"); @@ -2176,6 +2260,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } + text_ptr->compression = comp_type; text_ptr->key = png_ptr->chunkdata; text_ptr->lang = NULL; @@ -2189,6 +2274,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, text_ptr); png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; + if (ret) png_error(png_ptr, "Insufficient memory to store zTXt chunk"); } @@ -2216,6 +2302,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + if (--png_ptr->user_chunk_cache_max == 1) { png_warning(png_ptr, "No space in chunk cache for iTXt"); @@ -2252,6 +2339,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) { png_free(png_ptr, png_ptr->chunkdata); @@ -2263,6 +2351,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) for (lang = png_ptr->chunkdata; *lang; lang++) /* Empty loop */ ; + lang++; /* Skip NUL separator */ /* iTXt must have a language tag (possibly empty), two compression bytes, @@ -2277,6 +2366,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } + else { comp_flag = *lang++; @@ -2285,6 +2375,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) for (lang_key = lang; *lang_key; lang_key++) /* Empty loop */ ; + lang_key++; /* Skip NUL separator */ if (lang_key >= png_ptr->chunkdata + slength) @@ -2297,7 +2388,9 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) for (text = lang_key; *text; text++) /* Empty loop */ ; + text++; /* Skip NUL separator */ + if (text >= png_ptr->chunkdata + slength) { png_warning(png_ptr, "Malformed iTXt chunk"); @@ -2309,13 +2402,17 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) prefix_len = text - png_ptr->chunkdata; key=png_ptr->chunkdata; + if (comp_flag) png_decompress_chunk(png_ptr, comp_type, (size_t)length, prefix_len, &data_len); + else data_len = png_strlen(png_ptr->chunkdata + prefix_len); + text_ptr = (png_textp)png_malloc_warn(png_ptr, png_sizeof(png_text)); + if (text_ptr == NULL) { png_warning(png_ptr, "Not enough memory to process iTXt chunk"); @@ -2323,6 +2420,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } + text_ptr->compression = (int)comp_flag + 1; text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); text_ptr->lang = png_ptr->chunkdata + (lang - key); @@ -2336,6 +2434,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, text_ptr); png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; + if (ret) png_error(png_ptr, "Insufficient memory to store iTXt chunk"); } @@ -2362,6 +2461,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + if (--png_ptr->user_chunk_cache_max == 1) { png_warning(png_ptr, "No space in chunk cache for unknown chunk"); @@ -2406,19 +2506,23 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) length = (png_uint_32)65535L; } #endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, (png_charp)png_ptr->chunk_name, png_sizeof(png_ptr->unknown_chunk.name)); png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0'; png_ptr->unknown_chunk.size = (png_size_t)length; + if (length == 0) png_ptr->unknown_chunk.data = NULL; + else { png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); } + #ifdef PNG_READ_USER_CHUNKS_SUPPORTED if (png_ptr->read_user_chunk_fn != NULL) { @@ -2426,8 +2530,10 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) int ret; ret = (*(png_ptr->read_user_chunk_fn)) (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) { if (!(png_ptr->chunk_name[0] & 0x20)) @@ -2436,16 +2542,20 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) PNG_HANDLE_CHUNK_ALWAYS) #endif png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); } } + else #endif png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); png_ptr->unknown_chunk.data = NULL; } + else #endif skip = length; @@ -2493,11 +2603,13 @@ void /* PRIVATE */ png_combine_row(png_structp png_ptr, png_bytep row, int mask) { png_debug(1, "in png_combine_row"); + if (mask == 0xff) { png_memcpy(row, png_ptr->row_buf + 1, PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); } + else { switch (png_ptr->row_info.pixel_depth) @@ -2519,6 +2631,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) s_end = 7; s_inc = 1; } + else #endif { @@ -2546,11 +2659,13 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) sp++; dp++; } + else shift += s_inc; if (m == 1) m = 0x80; + else m >>= 1; } @@ -2574,6 +2689,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) s_end = 6; s_inc = 2; } + else #endif { @@ -2599,10 +2715,13 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) sp++; dp++; } + else shift += s_inc; + if (m == 1) m = 0x80; + else m >>= 1; } @@ -2626,6 +2745,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) s_end = 4; s_inc = 4; } + else #endif { @@ -2650,10 +2770,13 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) sp++; dp++; } + else shift += s_inc; + if (m == 1) m = 0x80; + else m >>= 1; } @@ -2681,6 +2804,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) if (m == 1) m = 0x80; + else m >>= 1; } @@ -2731,6 +2855,7 @@ png_do_read_interlace(png_structp png_ptr) s_end = 0; s_inc = -1; } + else #endif { @@ -2748,19 +2873,23 @@ png_do_read_interlace(png_structp png_ptr) { *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); *dp |= (png_byte)(v << dshift); + if (dshift == s_end) { dshift = s_start; dp--; } + else dshift += s_inc; } + if (sshift == s_end) { sshift = s_start; sp--; } + else sshift += s_inc; } @@ -2784,6 +2913,7 @@ png_do_read_interlace(png_structp png_ptr) s_end = 0; s_inc = -2; } + else #endif { @@ -2804,19 +2934,23 @@ png_do_read_interlace(png_structp png_ptr) { *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); *dp |= (png_byte)(v << dshift); + if (dshift == s_end) { dshift = s_start; dp--; } + else dshift += s_inc; } + if (sshift == s_end) { sshift = s_start; sp--; } + else sshift += s_inc; } @@ -2840,6 +2974,7 @@ png_do_read_interlace(png_structp png_ptr) s_end = 0; s_inc = -4; } + else #endif { @@ -2859,19 +2994,23 @@ png_do_read_interlace(png_structp png_ptr) { *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); *dp |= (png_byte)(v << dshift); + if (dshift == s_end) { dshift = s_start; dp--; } + else dshift += s_inc; } + if (sshift == s_end) { sshift = s_start; sp--; } + else sshift += s_inc; } @@ -2893,11 +3032,13 @@ png_do_read_interlace(png_structp png_ptr) int j; png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) { png_memcpy(dp, v, pixel_bytes); dp -= pixel_bytes; } + sp -= pixel_bytes; } break; @@ -2922,6 +3063,7 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, { case PNG_FILTER_VALUE_NONE: break; + case PNG_FILTER_VALUE_SUB: { png_uint_32 i; @@ -3015,8 +3157,10 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, /* if (pa <= pb && pa <= pc) p = a; + else if (pb <= pc) p = b; + else p = c; */ @@ -3064,13 +3208,17 @@ png_read_finish_row(png_structp png_ptr) if (png_ptr->interlaced) { png_ptr->row_number = 0; + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + do { png_ptr->pass++; + if (png_ptr->pass >= 7) break; + png_ptr->iwidth = (png_ptr->width + png_pass_inc[png_ptr->pass] - 1 - png_pass_start[png_ptr->pass]) / @@ -3082,9 +3230,11 @@ png_read_finish_row(png_structp png_ptr) png_pass_yinc[png_ptr->pass] - 1 - png_pass_ystart[png_ptr->pass]) / png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) continue; } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ break; } while (png_ptr->iwidth == 0); @@ -3102,6 +3252,7 @@ png_read_finish_row(png_structp png_ptr) png_ptr->zstream.next_out = (Byte *)&extra; png_ptr->zstream.avail_out = (uInt)1; + for (;;) { if (!(png_ptr->zstream.avail_in)) @@ -3116,23 +3267,29 @@ png_read_finish_row(png_structp png_ptr) png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); png_reset_crc(png_ptr); png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) png_error(png_ptr, "Not enough image data"); } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); png_ptr->idat_size -= png_ptr->zstream.avail_in; } ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) { if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || png_ptr->idat_size) png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; break; @@ -3201,12 +3358,14 @@ png_read_start_row(png_structp png_ptr) png_pass_start[png_ptr->pass]) / png_pass_inc[png_ptr->pass]; } + else #endif /* PNG_READ_INTERLACING_SUPPORTED */ { png_ptr->num_rows = png_ptr->height; png_ptr->iwidth = png_ptr->width; } + max_pixel_depth = png_ptr->pixel_depth; #ifdef PNG_READ_PACK_SUPPORTED @@ -3221,9 +3380,11 @@ png_read_start_row(png_structp png_ptr) { if (png_ptr->num_trans) max_pixel_depth = 32; + else max_pixel_depth = 24; } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { if (max_pixel_depth < 8) @@ -3231,6 +3392,7 @@ png_read_start_row(png_structp png_ptr) if (png_ptr->num_trans) max_pixel_depth *= 2; } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { if (png_ptr->num_trans) @@ -3247,17 +3409,21 @@ png_read_start_row(png_structp png_ptr) { if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { if (max_pixel_depth <= 8) max_pixel_depth = 16; + else max_pixel_depth = 32; } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { if (max_pixel_depth <= 32) max_pixel_depth = 32; + else max_pixel_depth = 64; } @@ -3278,20 +3444,24 @@ png_read_start_row(png_structp png_ptr) { if (max_pixel_depth <= 16) max_pixel_depth = 32; + else max_pixel_depth = 64; } + else { if (max_pixel_depth <= 8) { if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) max_pixel_depth = 32; + else max_pixel_depth = 24; } else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) max_pixel_depth = 64; + else max_pixel_depth = 48; } @@ -3318,6 +3488,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) */ row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + 1 + ((max_pixel_depth + 7) >> 3); + #ifdef PNG_MAX_MALLOC_64K if (row_bytes > (png_uint_32)65536L) png_error(png_ptr, "This image requires a row greater than 64KB"); @@ -3326,20 +3497,24 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if (row_bytes + 48 > png_ptr->old_big_row_buf_size) { png_free(png_ptr, png_ptr->big_row_buf); + if (png_ptr->interlaced) png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, row_bytes + 48); + else png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + png_ptr->old_big_row_buf_size = row_bytes + 48; #ifdef PNG_ALIGNED_MEMORY_SUPPORTED /* Use 16-byte aligned memory for row_buf with at least 16 bytes * of padding before and after row_buf. */ - png_ptr->row_buf = png_ptr->big_row_buf + 32 - - (((png_alloc_size_t)&(png_ptr->big_row_buf[0]) + 15) % 16); + png_ptr->row_buf = png_ptr->big_row_buf + 32 - + (((png_alloc_size_t)png_ptr->big_row_buf + 15) & 0x0F); + png_ptr->old_big_row_buf_size = row_bytes + 48; #else /* Use 32 bytes of padding before and 16 bytes after row_buf. */ @@ -3351,6 +3526,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) #ifdef PNG_MAX_MALLOC_64K if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) png_error(png_ptr, "This image requires a row greater than 64KB"); + #endif if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1)) png_error(png_ptr, "Row has too many bytes to allocate in memory"); @@ -3358,8 +3534,10 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size) { png_free(png_ptr, png_ptr->prev_row); + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( png_ptr->rowbytes + 1)); + png_ptr->old_prev_row_size = png_ptr->rowbytes + 1; } diff --git a/pngset.c b/pngset.c index 56af19de8..a93482a0a 100644 --- a/pngset.c +++ b/pngset.c @@ -1,7 +1,7 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -127,13 +127,16 @@ png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) png_warning(png_ptr, "Limiting gamma to 21474.83"); png_gamma = 21474.83; } + else png_gamma = file_gamma; + info_ptr->gamma = (float)png_gamma; #ifdef PNG_FIXED_POINT_SUPPORTED info_ptr->int_gamma = (int)(png_gamma*100000.+.5); #endif info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0.0) png_warning(png_ptr, "Setting gamma = 0"); } @@ -154,6 +157,7 @@ png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point png_warning(png_ptr, "Limiting gamma to 21474.83"); png_gamma = PNG_UINT_31_MAX; } + else { if (int_gamma < 0) @@ -161,6 +165,7 @@ png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point png_warning(png_ptr, "Setting negative gamma to zero"); png_gamma = 0; } + else png_gamma = int_gamma; } @@ -171,6 +176,7 @@ png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point info_ptr->int_gamma = png_gamma; #endif info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0) png_warning(png_ptr, "Setting gamma = 0"); } @@ -192,6 +198,7 @@ png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) { png_warning(png_ptr, "Invalid palette size, hIST allocation skipped"); + return; } @@ -209,6 +216,7 @@ png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) for (i = 0; i < info_ptr->num_palette; i++) png_ptr->hist[i] = hist[i]; + info_ptr->hist = png_ptr->hist; info_ptr->valid |= PNG_INFO_hIST; @@ -241,12 +249,16 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr, if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) info_ptr->channels = 3; + else info_ptr->channels = 1; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) info_ptr->channels++; + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); /* Check for potential overflow */ @@ -295,12 +307,14 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr, length = png_strlen(purpose) + 1; png_debug1(3, "allocating purpose for info (%lu bytes)", (unsigned long)length); + info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_purpose == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL purpose"); return; } + png_memcpy(info_ptr->pcal_purpose, purpose, length); png_debug(3, "storing X0, X1, type, and nparams in info"); @@ -312,6 +326,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr, length = png_strlen(units) + 1; png_debug1(3, "allocating units for info (%lu bytes)", (unsigned long)length); + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_units == NULL) { @@ -322,6 +337,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr, info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, (png_size_t)((nparams + 1) * png_sizeof(png_charp))); + if (info_ptr->pcal_params == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL params"); @@ -335,12 +351,15 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr, length = png_strlen(params[i]) + 1; png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, (unsigned long)length); + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_params[i] == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL parameter"); return; } + png_memcpy(info_ptr->pcal_params[i], params[i], length); } @@ -382,29 +401,39 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, info_ptr->scal_unit = (png_byte)unit; length = png_strlen(swidth) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)length); + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_width == NULL) { png_warning(png_ptr, "Memory allocation failed while processing sCAL"); return; } + png_memcpy(info_ptr->scal_s_width, swidth, length); length = png_strlen(sheight) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)length); + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_height == NULL) { png_free (png_ptr, info_ptr->scal_s_width); info_ptr->scal_s_width = NULL; + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; } + png_memcpy(info_ptr->scal_s_height, sheight, length); info_ptr->valid |= PNG_INFO_sCAL; info_ptr->free_me |= PNG_FREE_SCAL; @@ -444,6 +473,7 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr, { if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_error(png_ptr, "Invalid palette length"); + else { png_warning(png_ptr, "Invalid palette length"); @@ -463,6 +493,7 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr, */ png_ptr->palette = (png_colorp)png_calloc(png_ptr, PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); info_ptr->palette = png_ptr->palette; info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; @@ -596,6 +627,7 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr, } png_memcpy(new_iccp_name, name, length); new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); + if (new_iccp_profile == NULL) { png_free (png_ptr, new_iccp_name); @@ -603,6 +635,7 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr, "Insufficient memory to process iCCP profile"); return; } + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); @@ -626,6 +659,7 @@ png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, { int ret; ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + if (ret) png_error(png_ptr, "Insufficient memory to store text"); } @@ -658,15 +692,18 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, old_text = info_ptr->text; info_ptr->text = (png_textp)png_malloc_warn(png_ptr, (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) { png_free(png_ptr, old_text); return(1); } + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * png_sizeof(png_text))); png_free(png_ptr, old_text); } + else { info_ptr->max_text = num_text + 8; @@ -677,6 +714,7 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, return(1); info_ptr->free_me |= PNG_FREE_TEXT; } + png_debug1(3, "allocated %d entries for info_ptr->text", info_ptr->max_text); } @@ -704,10 +742,13 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, if (text_ptr[i].lang != NULL) lang_len = png_strlen(text_ptr[i].lang); + else lang_len = 0; + if (text_ptr[i].lang_key != NULL) lang_key_len = png_strlen(text_ptr[i].lang_key); + else lang_key_len = 0; } @@ -724,6 +765,7 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, #ifdef PNG_iTXt_SUPPORTED if (text_ptr[i].compression > 0) textp->compression = PNG_ITXT_COMPRESSION_NONE; + else #endif textp->compression = PNG_TEXT_COMPRESSION_NONE; @@ -738,8 +780,10 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, textp->key = (png_charp)png_malloc_warn(png_ptr, (png_size_t) (key_len + text_length + lang_len + lang_key_len + 4)); + if (textp->key == NULL) return(1); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text", (unsigned long)(png_uint_32) (key_len + lang_len + lang_key_len + text_length + 4), @@ -747,6 +791,7 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); *(textp->key + key_len) = '\0'; + if (text_ptr[i].compression > 0) { textp->lang = textp->key + key_len + 1; @@ -757,15 +802,18 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, *(textp->lang_key + lang_key_len) = '\0'; textp->text = textp->lang_key + lang_key_len + 1; } + else { textp->lang=NULL; textp->lang_key=NULL; textp->text = textp->key + key_len + 1; } + if (text_length) png_memcpy(textp->text, text_ptr[i].text, (png_size_t)(text_length)); + *(textp->text + text_length) = '\0'; #ifdef PNG_iTXt_SUPPORTED @@ -774,12 +822,14 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, textp->text_length = 0; textp->itxt_length = text_length; } + else #endif { textp->text_length = text_length; textp->itxt_length = 0; } + info_ptr->num_text++; png_debug1(3, "transferred text chunk %d", info_ptr->num_text); } @@ -824,6 +874,7 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr, /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ png_ptr->trans_alpha = info_ptr->trans_alpha = (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH); + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); } @@ -831,6 +882,7 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr, if (trans_color != NULL) { int sample_max = (1 << info_ptr->bit_depth); + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && (int)trans_color->gray > sample_max) || (info_ptr->color_type == PNG_COLOR_TYPE_RGB && @@ -839,13 +891,15 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr, (int)trans_color->blue > sample_max))) png_warning(png_ptr, "tRNS chunk has out-of-range samples for bit_depth"); - png_memcpy(&(info_ptr->trans_color), trans_color, - png_sizeof(png_color_16)); + + png_memcpy(&(info_ptr->trans_color), trans_color, png_sizeof(png_color_16)); + if (num_trans == 0) num_trans = 1; } info_ptr->num_trans = (png_uint_16)num_trans; + if (num_trans != 0) { info_ptr->valid |= PNG_INFO_tRNS; @@ -875,6 +929,7 @@ png_set_sPLT(png_structp png_ptr, np = (png_sPLT_tp)png_malloc_warn(png_ptr, (info_ptr->splt_palettes_num + nentries) * (png_size_t)png_sizeof(png_sPLT_t)); + if (np == NULL) { png_warning(png_ptr, "No memory for sPLT palettes"); @@ -883,6 +938,7 @@ png_set_sPLT(png_structp png_ptr, png_memcpy(np, info_ptr->splt_palettes, info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); info_ptr->splt_palettes=NULL; @@ -894,15 +950,18 @@ png_set_sPLT(png_structp png_ptr, length = png_strlen(from->name) + 1; to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length); + if (to->name == NULL) { png_warning(png_ptr, "Out of memory while processing sPLT chunk"); continue; } + png_memcpy(to->name, from->name, length); to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, (png_size_t)(from->nentries * png_sizeof(png_sPLT_entry))); + if (to->entries == NULL) { png_warning(png_ptr, @@ -911,8 +970,10 @@ png_set_sPLT(png_structp png_ptr, to->name = NULL; continue; } + png_memcpy(to->entries, from->entries, from->nentries * png_sizeof(png_sPLT_entry)); + to->nentries = from->nentries; to->depth = from->depth; } @@ -938,6 +999,7 @@ png_set_unknown_chunks(png_structp png_ptr, np = (png_unknown_chunkp)png_malloc_warn(png_ptr, (png_size_t)((info_ptr->unknown_chunks_num + num_unknowns) * png_sizeof(png_unknown_chunk))); + if (np == NULL) { png_warning(png_ptr, @@ -947,6 +1009,7 @@ png_set_unknown_chunks(png_structp png_ptr, png_memcpy(np, info_ptr->unknown_chunks, info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); info_ptr->unknown_chunks = NULL; @@ -964,16 +1027,19 @@ png_set_unknown_chunks(png_structp png_ptr, if (from->size == 0) to->data=NULL; + else { to->data = (png_bytep)png_malloc_warn(png_ptr, (png_size_t)from->size); + if (to->data == NULL) { png_warning(png_ptr, "Out of memory while processing unknown chunk"); to->size = 0; } + else png_memcpy(to->data, from->data, from->size); } @@ -1002,8 +1068,10 @@ png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) if (png_ptr == NULL) return (png_uint_32)0; + png_ptr->mng_features_permitted = (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + return (png_uint_32)png_ptr->mng_features_permitted; } #endif @@ -1017,17 +1085,21 @@ png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep int i, old_num_chunks; if (png_ptr == NULL) return; + if (num_chunks == 0) { if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; if (keep == PNG_HANDLE_CHUNK_ALWAYS) png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; } if (chunk_list == NULL) @@ -1036,6 +1108,7 @@ png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep new_list=(png_bytep)png_malloc(png_ptr, (png_size_t) (5*(num_chunks + old_num_chunks))); + if (png_ptr->chunk_list != NULL) { png_memcpy(new_list, png_ptr->chunk_list, @@ -1043,10 +1116,13 @@ png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep png_free(png_ptr, png_ptr->chunk_list); png_ptr->chunk_list=NULL; } + png_memcpy(new_list + 5*old_num_chunks, chunk_list, (png_size_t)(5*num_chunks)); + for (p = new_list + 5*old_num_chunks + 4, i = 0; inum_chunk_list = old_num_chunks + num_chunks; png_ptr->chunk_list = new_list; png_ptr->free_me |= PNG_FREE_LIST; @@ -1079,7 +1155,9 @@ png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + info_ptr->row_pointers = row_pointers; + if (row_pointers) info_ptr->valid |= PNG_INFO_IDAT; } @@ -1091,6 +1169,7 @@ png_set_compression_buffer_size(png_structp png_ptr, { if (png_ptr == NULL) return; + png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf_size = size; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); @@ -1119,6 +1198,7 @@ png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, */ if (png_ptr == NULL) return; + png_ptr->user_width_max = user_width_max; png_ptr->user_height_max = user_height_max; } @@ -1152,6 +1232,7 @@ png_set_benign_errors(png_structp png_ptr, int allowed) if (allowed) png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + else png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; } diff --git a/pngstruct.h b/pngstruct.h index 8bb5436a4..42c94cb12 100644 --- a/pngstruct.h +++ b/pngstruct.h @@ -5,7 +5,7 @@ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * - * Last changed in libpng version 1.5.0 - April 29, 2010 + * Last changed in libpng version 1.5.0 - May 6, 2010 * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/pngtest.c b/pngtest.c index f712dcbb3..91e1bd93c 100644 --- a/pngtest.c +++ b/pngtest.c @@ -1,7 +1,7 @@ /* pngtest.c - a simple test program to test libpng * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -42,7 +42,7 @@ # define FCLOSE(file) fclose(file) #ifndef PNG_STDIO_SUPPORTED - typedef FILE * png_FILE_p; +typedef FILE * png_FILE_p; #endif /* Makes pngtest verbose so we can find problems. */ @@ -112,18 +112,22 @@ read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) { if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) return; + if (status_pass != pass) { fprintf(stdout, "\n Pass %d: ", pass); status_pass = pass; status_dots = 31; } + status_dots--; + if (status_dots == 0) { fprintf(stdout, "\n "); status_dots=30; } + fprintf(stdout, "r"); } @@ -134,6 +138,7 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) { if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) return; + fprintf(stdout, "w"); } @@ -167,7 +172,8 @@ void PNGCBAPI count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) { png_bytep dp = data; - if (png_ptr == NULL)return; + if (png_ptr == NULL) + return; /* Contents of row_info: * png_uint_32 width width of row @@ -184,41 +190,49 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) { int pos = 0; png_uint_32 n, nstop; + for (n = 0, nstop=row_info->width; nbit_depth == 1) { if (((*dp << pos++ ) & 0x80) == 0) zero_samples++; + if (pos == 8) { pos = 0; dp++; } } + if (row_info->bit_depth == 2) { if (((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++; + if (pos == 8) { pos = 0; dp++; } } + if (row_info->bit_depth == 4) { if (((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++; + if (pos == 8) { pos = 0; dp++; } } + if (row_info->bit_depth == 8) if (*dp++ == 0) zero_samples++; + if (row_info->bit_depth == 16) { if ((*dp | *(dp+1)) == 0) @@ -241,10 +255,12 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) if (row_info->bit_depth == 8) if (*dp++ == 0) zero_samples++; + if (row_info->bit_depth == 16) { if ((*dp | *(dp+1)) == 0) zero_samples++; + dp+=2; } } @@ -321,6 +337,7 @@ pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) png_size_t read, remaining, err; check = 0; remaining = length; + do { read = MIN(NEAR_BUF_SIZE, remaining); @@ -335,6 +352,7 @@ pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) } while (remaining != 0); } + if (check != length) png_error(png_ptr, "read Error"); } @@ -361,6 +379,7 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) png_size_t check; check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); + if (check != length) { png_error(png_ptr, "Write Error"); @@ -385,16 +404,19 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) /* Check if data really is near. If so, use usual code. */ near_data = (png_byte *)CVT_PTR_NOCHECK(data); io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); + if ((png_bytep)near_data == data) { check = fwrite(near_data, 1, length, io_ptr); } + else { png_byte buf[NEAR_BUF_SIZE]; png_size_t written, remaining, err; check = 0; remaining = length; + do { written = MIN(NEAR_BUF_SIZE, remaining); @@ -409,6 +431,7 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) } while (remaining != 0); } + if (check != length) { png_error(png_ptr, "Write Error"); @@ -427,8 +450,10 @@ pngtest_warning(png_structp png_ptr, png_const_charp message) PNG_CONST char *name = "UNKNOWN (ERROR!)"; char *test; test = png_get_error_ptr(png_ptr); + if (test == NULL) fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + else fprintf(STDERR, "%s: libpng warning: %s\n", test, message); } @@ -502,12 +527,16 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) current_allocation += size; total_allocation += size; num_allocations ++; + if (current_allocation > maximum_allocation) maximum_allocation = current_allocation; + pinfo->pointer = png_malloc(png_ptr, size); /* Restore malloc_fn and free_fn */ + png_set_mem_fn(png_ptr, NULL, png_debug_malloc, png_debug_free); + if (size != 0 && pinfo->pointer == NULL) { current_allocation -= size; @@ -515,13 +544,16 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) png_error(png_ptr, "out of memory in pngtest->png_debug_malloc"); } + pinfo->next = pinformation; pinformation = pinfo; /* Make sure the caller isn't assuming zeroed memory. */ png_memset(pinfo->pointer, 0xdd, pinfo->size); + if (verbose) printf("png_malloc %lu bytes at %p\n", (unsigned long)size, pinfo->pointer); + return (png_voidp)(pinfo->pointer); } } @@ -532,6 +564,7 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) { if (png_ptr == NULL) fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + if (ptr == 0) { #if 0 /* This happens all the time. */ @@ -543,9 +576,11 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) /* Unlink the element from the list. */ { memory_infop FAR *ppinfo = &pinformation; + for (;;) { memory_infop pinfo = *ppinfo; + if (pinfo->pointer == ptr) { *ppinfo = pinfo->next; @@ -559,11 +594,13 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) pinfo = NULL; break; } + if (pinfo->next == NULL) { fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); break; } + ppinfo = &pinfo->next; } } @@ -571,6 +608,7 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) /* Finally free the data. */ if (verbose) printf("Freeing %p\n", ptr); + png_free_default(png_ptr, ptr); ptr = NULL; } @@ -617,8 +655,10 @@ static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, /* Found sTER chunk */ if (chunk->size != 1) return (-1); /* Error return */ + if (chunk->data[0] != 0 && chunk->data[0] != 1) return (-1); /* Invalid mode */ + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); my_user_chunk_data[0]=chunk->data[0]+1; return (1); @@ -762,6 +802,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #ifdef PNG_WRITE_SUPPORTED pngtest_debug("Setting jmpbuf for write struct"); #ifdef USE_FAR_KEYWORD + if (setjmp(png_jmpbuf)) #else if (setjmp(png_jmpbuf(write_ptr))) @@ -777,6 +818,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) FCLOSE(fpout); return (1); } + #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(write_ptr), png_jmpbuf, png_sizeof(jmp_buf)); #endif @@ -800,6 +842,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) # endif # endif #endif + if (status_dots_requested == 1) { #ifdef PNG_WRITE_SUPPORTED @@ -807,6 +850,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #endif png_set_read_status_fn(read_ptr, read_row_callback); } + else { #ifdef PNG_WRITE_SUPPORTED @@ -818,8 +862,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #ifdef 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 @@ -866,6 +912,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) { @@ -888,6 +935,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) { @@ -1053,6 +1101,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_memcpy(tIME_string, png_convert_to_rfc1123(read_ptr, mod_time), png_sizeof(tIME_string)); + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; tIME_chunk_present++; #endif /* PNG_TIME_RFC1123_SUPPORTED */ @@ -1086,6 +1135,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_unknown_chunkp unknowns; int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, &unknowns); + if (num_unknowns) { png_size_t i; @@ -1121,9 +1171,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) if (verbose) fprintf(STDERR, "\n stereo mode = %lu\n", (unsigned long)(user_chunk_data[0] - 1)); + ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); } + if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) { png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; @@ -1136,6 +1188,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) (unsigned long)user_chunk_data[1], (unsigned long)user_chunk_data[2], (unsigned long)user_chunk_data[3]); + png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); @@ -1149,6 +1202,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) pngtest_debug("Allocating row buffer..."); row_buf = (png_bytep)png_malloc(read_ptr, png_get_rowbytes(read_ptr, read_info_ptr)); + pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); #endif /* SINGLE_ROWBUF_ALLOC */ pngtest_debug("Writing row data"); @@ -1177,8 +1231,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); row_buf = (png_bytep)png_malloc(read_ptr, png_get_rowbytes(read_ptr, read_info_ptr)); + pngtest_debug2("\t0x%08lx (%u bytes)", (unsigned long)row_buf, png_get_rowbytes(read_ptr, read_info_ptr)); + #endif /* !SINGLE_ROWBUF_ALLOC */ png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); @@ -1240,6 +1296,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_memcpy(tIME_string, png_convert_to_rfc1123(read_ptr, mod_time), png_sizeof(tIME_string)); + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; tIME_chunk_present++; #endif /* PNG_TIME_RFC1123_SUPPORTED */ @@ -1250,8 +1307,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { png_unknown_chunkp unknowns; int num_unknowns; + num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, &unknowns); + if (num_unknowns) { png_size_t i; @@ -1326,6 +1385,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { fprintf(STDERR, "\nFiles %s and %s are of a different size\n", inname, outname); + if (wrote_question == 0) { fprintf(STDERR, @@ -1338,6 +1398,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) ZLIB_VERSION); wrote_question = 1; } + FCLOSE(fpin); FCLOSE(fpout); return (0); @@ -1349,6 +1410,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) if (png_memcmp(inbuf, outbuf, num_in)) { fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + if (wrote_question == 0) { fprintf(STDERR, @@ -1361,6 +1423,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) ZLIB_VERSION); wrote_question = 1; } + FCLOSE(fpin); FCLOSE(fpout); return (0); @@ -1395,6 +1458,7 @@ main(int argc, char *argv[]) fprintf(STDERR, " library (%lu):%s", (unsigned long)png_access_version_number(), png_get_header_version(NULL)); + /* Show the version of libpng used in building the application */ fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, PNG_HEADER_VERSION_STRING); @@ -1428,6 +1492,7 @@ main(int argc, char *argv[]) multiple = 1; status_dots_requested = 0; } + else if (strcmp(argv[1], "-mv") == 0 || strcmp(argv[1], "-vm") == 0 ) { @@ -1435,12 +1500,14 @@ main(int argc, char *argv[]) verbose = 1; status_dots_requested = 1; } + else if (strcmp(argv[1], "-v") == 0) { verbose = 1; status_dots_requested = 1; inname = argv[2]; } + else { inname = argv[1]; @@ -1494,9 +1561,11 @@ main(int argc, char *argv[]) #ifdef PNG_TIME_RFC1123_SUPPORTED if (tIME_chunk_present != 0) fprintf(STDERR, " tIME = %s\n", tIME_string); + tIME_chunk_present = 0; #endif /* PNG_TIME_RFC1123_SUPPORTED */ } + else { fprintf(STDERR, " FAIL\n"); @@ -1506,12 +1575,14 @@ main(int argc, char *argv[]) if (allocation_now != current_allocation) fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", current_allocation - allocation_now); + if (current_allocation != 0) { memory_infop pinfo = pinformation; fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", current_allocation); + while (pinfo != NULL) { fprintf(STDERR, " %lu bytes at %x\n", @@ -1533,6 +1604,7 @@ main(int argc, char *argv[]) num_allocations); #endif } + else { int i; @@ -1542,11 +1614,17 @@ main(int argc, char *argv[]) #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG int allocation_now = current_allocation; #endif - if (i == 1) status_dots_requested = 1; - else if (verbose == 0)status_dots_requested = 0; + if (i == 1) + status_dots_requested = 1; + + else if (verbose == 0) + status_dots_requested = 0; + if (i == 0 || verbose == 1 || ierror != 0) fprintf(STDERR, "\n Testing %s:", inname); + kerror = test_one_file(inname, outname); + if (kerror == 0) { if (verbose == 1 || i == 2) @@ -1572,10 +1650,12 @@ main(int argc, char *argv[]) #endif /* PNG_TIME_RFC1123_SUPPORTED */ } } + else { if (verbose == 0 && i != 2) fprintf(STDERR, "\n Testing %s:", inname); + fprintf(STDERR, " FAIL\n"); ierror += kerror; } @@ -1583,12 +1663,14 @@ main(int argc, char *argv[]) if (allocation_now != current_allocation) fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", current_allocation - allocation_now); + if (current_allocation != 0) { memory_infop pinfo = pinformation; fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", current_allocation); + while (pinfo != NULL) { fprintf(STDERR, " %lu bytes at %x\n", @@ -1626,8 +1708,10 @@ main(int argc, char *argv[]) if (ierror == 0) fprintf(STDERR, " libpng passes test\n"); + else fprintf(STDERR, " libpng FAILS test\n"); + return (int)(ierror != 0); } diff --git a/pngtrans.c b/pngtrans.c index 187c894ee..726410fdc 100644 --- a/pngtrans.c +++ b/pngtrans.c @@ -1,7 +1,7 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -24,6 +24,7 @@ png_set_bgr(png_structp png_ptr) if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_BGR; } #endif @@ -37,6 +38,7 @@ png_set_swap(png_structp png_ptr) if (png_ptr == NULL) return; + if (png_ptr->bit_depth == 16) png_ptr->transformations |= PNG_SWAP_BYTES; } @@ -51,6 +53,7 @@ png_set_packing(png_structp png_ptr) if (png_ptr == NULL) return; + if (png_ptr->bit_depth < 8) { png_ptr->transformations |= PNG_PACK; @@ -68,6 +71,7 @@ png_set_packswap(png_structp png_ptr) if (png_ptr == NULL) return; + if (png_ptr->bit_depth < 8) png_ptr->transformations |= PNG_PACKSWAP; } @@ -81,6 +85,7 @@ png_set_shift(png_structp png_ptr, png_color_8p true_bits) if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_SHIFT; png_ptr->shift = *true_bits; } @@ -116,10 +121,13 @@ png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_FILLER; png_ptr->filler = (png_uint_16)filler; + if (filler_loc == PNG_FILLER_AFTER) png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + else png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; @@ -150,6 +158,7 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) if (png_ptr == NULL) return; + png_set_filler(png_ptr, filler, filler_loc); png_ptr->transformations |= PNG_ADD_ALPHA; } @@ -165,6 +174,7 @@ png_set_swap_alpha(png_structp png_ptr) if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_SWAP_ALPHA; } #endif @@ -178,6 +188,7 @@ png_set_invert_alpha(png_structp png_ptr) if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_INVERT_ALPHA; } #endif @@ -190,6 +201,7 @@ png_set_invert_mono(png_structp png_ptr) if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_INVERT_MONO; } @@ -214,6 +226,7 @@ png_do_invert(png_row_infop row_info, png_bytep row) rp++; } } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && row_info->bit_depth == 8) { @@ -227,6 +240,7 @@ png_do_invert(png_row_infop row_info, png_bytep row) rp += 2; } } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && row_info->bit_depth == 16) { @@ -251,8 +265,7 @@ png_do_swap(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_swap"); - if ( - row_info->bit_depth == 16) + if (row_info->bit_depth == 16) { png_bytep rp = row; png_uint_32 i; @@ -380,8 +393,7 @@ png_do_packswap(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_packswap"); - if ( - row_info->bit_depth < 8) + if (row_info->bit_depth < 8) { png_bytep rp, end, table; @@ -389,10 +401,13 @@ png_do_packswap(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 1) table = (png_bytep)onebppswaptable; + else if (row_info->bit_depth == 2) table = (png_bytep)twobppswaptable; + else if (row_info->bit_depth == 4) table = (png_bytep)fourbppswaptable; + else return; @@ -435,6 +450,7 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) sp++; } } + /* This converts from XRGB or ARGB to RGB */ else { @@ -449,6 +465,7 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) row_info->pixel_depth = 24; row_info->rowbytes = row_width * 3; } + else /* if (row_info->bit_depth == 16) */ { if (flags & PNG_FLAG_FILLER_AFTER) @@ -472,6 +489,7 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) sp += 2; } } + else { /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ @@ -492,11 +510,13 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) *dp++ = *sp++; } } + row_info->pixel_depth = 48; row_info->rowbytes = row_width * 6; } row_info->channels = 3; } + else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && (flags & PNG_FLAG_STRIP_ALPHA))) && @@ -513,6 +533,7 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) sp++; } } + else { /* This converts from XG or AG to G */ @@ -522,9 +543,11 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) *dp++ = *sp++; } } + row_info->pixel_depth = 8; row_info->rowbytes = row_width; } + else /* if (row_info->bit_depth == 16) */ { if (flags & PNG_FLAG_FILLER_AFTER) @@ -538,6 +561,7 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) sp += 2; } } + else { /* This converts from XXGG or AAGG to GG */ @@ -548,11 +572,13 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) *dp++ = *sp++; } } + row_info->pixel_depth = 16; row_info->rowbytes = row_width * 2; } row_info->channels = 1; } + if (flags & PNG_FLAG_STRIP_ALPHA) row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; } @@ -566,8 +592,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_bgr"); - if ( - (row_info->color_type & PNG_COLOR_MASK_COLOR)) + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) { png_uint_32 row_width = row_info->width; if (row_info->bit_depth == 8) @@ -584,6 +609,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) *(rp + 2) = save; } } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { png_bytep rp; @@ -597,6 +623,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) } } } + else if (row_info->bit_depth == 16) { if (row_info->color_type == PNG_COLOR_TYPE_RGB) @@ -614,6 +641,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) *(rp + 5) = save; } } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { png_bytep rp; @@ -665,6 +693,7 @@ png_get_user_transform_ptr(png_structp png_ptr) { if (png_ptr == NULL) return (NULL); + #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED return ((png_voidp)png_ptr->user_transform_ptr); #else diff --git a/pngwio.c b/pngwio.c index 4e4891a5a..f8842fedd 100644 --- a/pngwio.c +++ b/pngwio.c @@ -1,7 +1,7 @@ /* pngwio.c - functions for data output * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -34,6 +34,7 @@ png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { if (png_ptr->write_data_fn != NULL ) (*(png_ptr->write_data_fn))(png_ptr, data, length); + else png_error(png_ptr, "Call to NULL write function"); } @@ -52,7 +53,9 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) if (png_ptr == NULL) return; + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + if (check != length) png_error(png_ptr, "Write Error"); } @@ -74,24 +77,29 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) if (png_ptr == NULL) return; + /* Check if data really is near. If so, use usual code. */ near_data = (png_byte *)CVT_PTR_NOCHECK(data); io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) { check = fwrite(near_data, 1, length, io_ptr); } + else { png_byte buf[NEAR_BUF_SIZE]; png_size_t written, remaining, err; check = 0; remaining = length; + do { written = MIN(NEAR_BUF_SIZE, remaining); png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ err = fwrite(buf, 1, written, io_ptr); + if (err != written) break; @@ -103,6 +111,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) } while (remaining != 0); } + if (check != length) png_error(png_ptr, "Write Error"); } @@ -127,8 +136,10 @@ void PNGCBAPI png_default_flush(png_structp png_ptr) { png_FILE_p io_ptr; + if (png_ptr == NULL) return; + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); fflush(io_ptr); } @@ -154,7 +165,7 @@ png_default_flush(png_structp png_ptr) * arguments a pointer to a png_struct. After a call to * the flush function, there should be no data in any buffers * or pending transmission. If the output method doesn't do - * any buffering of ouput, a function prototype must still be + * any buffering of output, a function prototype must still be * supplied although it doesn't have to do anything. If * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile * time, output_flush_fn will be ignored, although it must be @@ -185,11 +196,13 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, #ifdef PNG_WRITE_FLUSH_SUPPORTED # ifdef PNG_STDIO_SUPPORTED + if (output_flush_fn != NULL) png_ptr->output_flush_fn = output_flush_fn; else png_ptr->output_flush_fn = png_default_flush; + # else png_ptr->output_flush_fn = output_flush_fn; # endif @@ -199,6 +212,7 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, if (png_ptr->read_data_fn != NULL) { png_ptr->read_data_fn = NULL; + png_warning(png_ptr, "Can't set both read_data_fn and write_data_fn in the" " same structure"); diff --git a/pngwrite.c b/pngwrite.c index f6a46e44c..1aa78959c 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -1,7 +1,7 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -31,10 +31,12 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) if (png_ptr == NULL || info_ptr == NULL) return; + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) { /* 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)) @@ -43,6 +45,7 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) png_ptr->mng_features_permitted = 0; } #endif + /* 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, @@ -71,6 +74,7 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) if (info_ptr->valid & PNG_INFO_sRGB) png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); #endif + #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, @@ -80,6 +84,7 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) if (info_ptr->valid & PNG_INFO_sBIT) png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); #endif + #ifdef PNG_WRITE_cHRM_SUPPORTED if (info_ptr->valid & PNG_INFO_cHRM) { @@ -100,6 +105,7 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) #endif } #endif + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED if (info_ptr->unknown_chunks_num) { @@ -112,6 +118,7 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) 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) && @@ -120,6 +127,7 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) { if (up->size == 0) png_warning(png_ptr, "Writing zero-length unknown chunk"); + png_write_chunk(png_ptr, up->name, up->data, up->size); } } @@ -146,6 +154,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) if (info_ptr->valid & PNG_INFO_PLTE) 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"); @@ -170,15 +179,18 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) if (info_ptr->valid & PNG_INFO_bKGD) png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); #endif + #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 + #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 + #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, @@ -189,14 +201,17 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) #ifdef PNG_sCAL_SUPPORTED if (info_ptr->valid & PNG_INFO_sCAL) #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 /* !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); #endif /* FIXED_POINT */ + #endif /* FLOATING_POINT */ #else /* !WRITE_sCAL */ png_warning(png_ptr, @@ -247,6 +262,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) /* Mark this chunk as written */ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; } + /* If we want a compressed text chunk */ else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) { @@ -261,6 +277,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) /* 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) { #ifdef PNG_WRITE_tEXt_SUPPORTED @@ -315,6 +332,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr) if (png_ptr == NULL) return; + if (!(png_ptr->mode & PNG_HAVE_IDAT)) png_error(png_ptr, "No IDATs written into file"); @@ -329,6 +347,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr) if ((info_ptr->valid & PNG_INFO_tIME) && !(png_ptr->mode & PNG_WROTE_tIME)) png_write_tIME(png_ptr, &(info_ptr->mod_time)); + #endif #ifdef PNG_WRITE_TEXT_SUPPORTED /* Loop through comment chunks */ @@ -353,6 +372,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr) /* 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) { #ifdef PNG_WRITE_zTXt_SUPPORTED @@ -366,6 +386,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr) /* 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) { #ifdef PNG_WRITE_tEXt_SUPPORTED @@ -539,6 +560,7 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, { #ifdef PNG_CONSOLE_IO_SUPPORTED char msg[80]; + if (user_png_ver) { png_snprintf2(msg, 80, @@ -561,6 +583,7 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, /* Initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; + if (!png_cleanup_needed) { png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, @@ -568,6 +591,7 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, if (png_ptr->zbuf == NULL) png_cleanup_needed = 1; } + if (png_cleanup_needed) { /* Clean up PNG structure and deallocate any memory. */ @@ -674,6 +698,7 @@ png_write_row(png_structp png_ptr, png_bytep row) 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"); @@ -684,18 +709,22 @@ png_write_row(png_structp png_ptr, png_bytep row) 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"); #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"); #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"); #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"); @@ -838,6 +867,7 @@ png_set_flush(png_structp png_ptr, int nrows) if (png_ptr == NULL) return; + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); } @@ -851,6 +881,7 @@ png_write_flush(png_structp png_ptr) if (png_ptr == NULL) return; + /* We have already written out all of the data */ if (png_ptr->row_number >= png_ptr->num_rows) return; @@ -868,6 +899,7 @@ png_write_flush(png_structp png_ptr) { if (png_ptr->zstream.msg != NULL) png_error(png_ptr, png_ptr->zstream.msg); + else png_error(png_ptr, "zlib error"); } @@ -880,7 +912,7 @@ png_write_flush(png_structp png_ptr) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; wrote_IDAT = 1; } - } while(wrote_IDAT == 1); + } while (wrote_IDAT == 1); /* 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) @@ -1043,10 +1075,12 @@ png_set_filter(png_structp png_ptr, int method, int filters) 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 if (method == PNG_FILTER_TYPE_BASE) { @@ -1059,15 +1093,20 @@ png_set_filter(png_structp png_ptr, int method, int filters) #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 @@ -1102,6 +1141,7 @@ png_set_filter(png_structp png_ptr, int method, int filters) png_warning(png_ptr, "Can't add Up filter after starting"); png_ptr->do_filter &= ~PNG_FILTER_UP; } + else { png_ptr->up_row = (png_bytep)png_malloc(png_ptr, @@ -1117,6 +1157,7 @@ png_set_filter(png_structp png_ptr, int method, int filters) png_warning(png_ptr, "Can't add Average filter after starting"); png_ptr->do_filter &= ~PNG_FILTER_AVG; } + else { png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, @@ -1133,6 +1174,7 @@ png_set_filter(png_structp png_ptr, int method, int filters) png_warning(png_ptr, "Can't add Paeth filter after starting"); png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); } + else { png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, @@ -1169,6 +1211,7 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, if (png_ptr == NULL) return; + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) { png_warning(png_ptr, "Unknown filter heuristic method"); @@ -1210,6 +1253,7 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) { png_ptr->inv_filter_weights[i] = @@ -1224,10 +1268,12 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, png_ptr->inv_filter_weights[i] = png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; } + else { png_ptr->inv_filter_weights[i] = (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); } @@ -1266,10 +1312,12 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, png_ptr->inv_filter_costs[i] = png_ptr->filter_costs[i] = PNG_COST_FACTOR; } + else if (filter_costs[i] >= 1.0) { png_ptr->inv_filter_costs[i] = (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); } @@ -1284,6 +1332,7 @@ png_set_compression_level(png_structp png_ptr, int level) if (png_ptr == NULL) return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; png_ptr->zlib_level = level; } @@ -1295,6 +1344,7 @@ png_set_compression_mem_level(png_structp png_ptr, int mem_level) if (png_ptr == NULL) return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; png_ptr->zlib_mem_level = mem_level; } @@ -1306,6 +1356,7 @@ png_set_compression_strategy(png_structp png_ptr, int strategy) if (png_ptr == NULL) return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; png_ptr->zlib_strategy = strategy; } @@ -1315,10 +1366,13 @@ 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 */ if (window_bits == 8) @@ -1326,6 +1380,7 @@ png_set_compression_window_bits(png_structp png_ptr, int window_bits) png_warning(png_ptr, "Compression window is being reset to 512"); window_bits = 9; } + #endif png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; png_ptr->zlib_window_bits = window_bits; @@ -1338,8 +1393,10 @@ png_set_compression_method(png_structp png_ptr, int 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; png_ptr->zlib_method = method; } @@ -1349,6 +1406,7 @@ 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; } @@ -1361,6 +1419,7 @@ png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr if (png_ptr == NULL) return; + png_ptr->transformations |= PNG_USER_TRANSFORM; png_ptr->write_user_transform_fn = write_user_transform_fn; } @@ -1411,6 +1470,7 @@ png_write_png(png_structp png_ptr, png_infop info_ptr, /* 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 diff --git a/pngwtran.c b/pngwtran.c index 6195d8e6e..4236e1023 100644 --- a/pngwtran.c +++ b/pngwtran.c @@ -1,7 +1,7 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -41,41 +41,50 @@ png_do_write_transformations(png_structp png_ptr) /* png_byte pixel_depth; bits per pixel (depth*channels) */ png_ptr->row_buf + 1); /* start of pixel data for row */ #endif + #ifdef PNG_WRITE_FILLER_SUPPORTED if (png_ptr->transformations & PNG_FILLER) png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr->flags); #endif + #ifdef PNG_WRITE_PACKSWAP_SUPPORTED if (png_ptr->transformations & PNG_PACKSWAP) png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_PACK_SUPPORTED if (png_ptr->transformations & PNG_PACK) png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, (png_uint_32)png_ptr->bit_depth); #endif + #ifdef PNG_WRITE_SWAP_SUPPORTED if (png_ptr->transformations & PNG_SWAP_BYTES) png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_SHIFT_SUPPORTED if (png_ptr->transformations & PNG_SHIFT) png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, &(png_ptr->shift)); #endif + #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED if (png_ptr->transformations & PNG_SWAP_ALPHA) png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED if (png_ptr->transformations & PNG_INVERT_ALPHA) png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_BGR_SUPPORTED if (png_ptr->transformations & PNG_BGR) png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_INVERT_SUPPORTED if (png_ptr->transformations & PNG_INVERT_MONO) png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); @@ -113,9 +122,12 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) { if (*sp != 0) v |= mask; + sp++; + if (mask > 1) mask >>= 1; + else { mask = 0x80; @@ -124,8 +136,10 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) v = 0; } } + if (mask != 0x80) *dp = (png_byte)v; + break; } case 2: @@ -139,12 +153,14 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp = row; shift = 6; v = 0; + for (i = 0; i < row_width; i++) { png_byte value; value = (png_byte)(*sp & 0x03); v |= (value << shift); + if (shift == 0) { shift = 6; @@ -152,12 +168,16 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp++; v = 0; } + else shift -= 2; + sp++; } + if (shift != 6) *dp = (png_byte)v; + break; } case 4: @@ -171,6 +191,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp = row; shift = 4; v = 0; + for (i = 0; i < row_width; i++) { png_byte value; @@ -185,13 +206,16 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp++; v = 0; } + else shift -= 4; sp++; } + if (shift != 4) *dp = (png_byte)v; + break; } } @@ -216,8 +240,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) { png_debug(1, "in png_do_shift"); - if ( - row_info->color_type != PNG_COLOR_TYPE_PALETTE) + if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) { int shift_start[4], shift_dec[4]; int channels = 0; @@ -227,19 +250,23 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) shift_start[channels] = row_info->bit_depth - bit_depth->red; shift_dec[channels] = bit_depth->red; channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; shift_dec[channels] = bit_depth->green; channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; shift_dec[channels] = bit_depth->blue; channels++; } + else { shift_start[channels] = row_info->bit_depth - bit_depth->gray; shift_dec[channels] = bit_depth->gray; channels++; } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) { shift_start[channels] = row_info->bit_depth - bit_depth->alpha; @@ -257,8 +284,10 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) if (bit_depth->gray == 1 && row_info->bit_depth == 2) mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) mask = 0x11; + else mask = 0xff; @@ -269,10 +298,12 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) v = *bp; *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) { if (j > 0) *bp |= (png_byte)((v << j) & 0xff); + else *bp |= (png_byte)((v >> (-j)) & mask); } @@ -293,10 +324,12 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) v = *bp; *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) { if (j > 0) *bp |= (png_byte)((v << j) & 0xff); + else *bp |= (png_byte)((v >> (-j)) & 0xff); } @@ -316,10 +349,12 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) { if (j > 0) value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); } @@ -346,6 +381,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) { png_byte save = *(sp++); @@ -355,6 +391,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) *(dp++) = save; } } + else { /* This converts from AARRGGBB to RRGGBBAA */ @@ -378,6 +415,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) } } } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (row_info->bit_depth == 8) @@ -394,6 +432,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) *(dp++) = save; } } + else { /* This converts from AAGG to GGAA */ @@ -432,6 +471,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) { /* Does nothing @@ -443,6 +483,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) *(dp++) = (png_byte)(255 - *(sp++)); } } + else { /* This inverts the alpha channel in RRGGBBAA */ @@ -466,6 +507,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) } } } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (row_info->bit_depth == 8) @@ -481,6 +523,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) *(dp++) = (png_byte)(255 - *(sp++)); } } + else { /* This inverts the alpha channel in GGAA */ @@ -511,8 +554,7 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_write_intrapixel"); - if ( - (row_info->color_type & PNG_COLOR_MASK_COLOR)) + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) { int bytes_per_pixel; png_uint_32 row_width = row_info->width; @@ -523,8 +565,10 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) if (row_info->color_type == PNG_COLOR_TYPE_RGB) bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) bytes_per_pixel = 4; + else return; @@ -534,6 +578,7 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); } } + else if (row_info->bit_depth == 16) { png_bytep rp; @@ -541,8 +586,10 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) if (row_info->color_type == PNG_COLOR_TYPE_RGB) bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) bytes_per_pixel = 8; + else return; diff --git a/pngwutil.c b/pngwutil.c index 876437cf5..cd04c8960 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -1,7 +1,7 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.5.0 [April 29, 2010] + * Last changed in libpng 1.5.0 [May 6, 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.) @@ -75,6 +75,7 @@ png_write_sig(png_structp png_ptr) /* Write the rest of the 8 byte signature */ png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], (png_size_t)(8 - png_ptr->sig_bytes)); + if (png_ptr->sig_bytes < 3) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; } @@ -151,6 +152,7 @@ png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) /* Write the data, and run the CRC over it */ if (png_ptr == NULL) return; + if (data != NULL && length > 0) { png_write_data(png_ptr, data, length); @@ -257,6 +259,7 @@ png_text_compress(png_structp png_ptr, { /* Compress the data */ ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) { /* Error */ @@ -265,6 +268,7 @@ png_text_compress(png_structp png_ptr, else png_error(png_ptr, "zlib error"); } + /* Check to see if we need more room */ if (!(png_ptr->zstream.avail_out)) { @@ -339,6 +343,7 @@ png_text_compress(png_structp png_ptr, old_max * png_sizeof(png_charp)); png_free(png_ptr, old_ptr); } + else comp->output_ptr = (png_charpp)png_malloc(png_ptr, (png_alloc_size_t)(comp->max_output_ptr * @@ -349,8 +354,10 @@ png_text_compress(png_structp png_ptr, comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, (png_alloc_size_t)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, png_ptr->zbuf_size); + comp->num_output_ptr++; /* and reset the buffer pointers */ @@ -363,6 +370,7 @@ png_text_compress(png_structp png_ptr, /* We got an error */ if (png_ptr->zstream.msg != NULL) png_error(png_ptr, png_ptr->zstream.msg); + else png_error(png_ptr, "zlib error"); } @@ -387,6 +395,7 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) { png_write_chunk_data(png_ptr, (png_bytep)comp->input, (png_size_t)comp->input_len); + return; } @@ -395,10 +404,12 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) { png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i], (png_size_t)png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); } if (comp->max_output_ptr != 0) png_free(png_ptr, comp->output_ptr); + /* Write anything left in zbuf */ if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) png_write_chunk_data(png_ptr, png_ptr->zbuf, @@ -443,11 +454,14 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, "Invalid bit depth for grayscale image"); } break; + case PNG_COLOR_TYPE_RGB: if (bit_depth != 8 && bit_depth != 16) png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; break; + case PNG_COLOR_TYPE_PALETTE: switch (bit_depth) { @@ -461,16 +475,21 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_error(png_ptr, "Invalid bit depth for paletted image"); } break; + case PNG_COLOR_TYPE_GRAY_ALPHA: if (bit_depth != 8 && bit_depth != 16) png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; break; + case PNG_COLOR_TYPE_RGB_ALPHA: if (bit_depth != 8 && bit_depth != 16) png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; break; + default: png_error(png_ptr, "Invalid image color type specified"); } @@ -506,7 +525,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, #ifdef PNG_WRITE_INTERLACING_SUPPORTED if (interlace_type != PNG_INTERLACE_NONE && - interlace_type != PNG_INTERLACE_ADAM7) + interlace_type != PNG_INTERLACE_ADAM7) { png_warning(png_ptr, "Invalid interlace type specified"); interlace_type = PNG_INTERLACE_ADAM7; @@ -549,11 +568,13 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; + if (!(png_ptr->do_filter)) { if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || png_ptr->bit_depth < 8) png_ptr->do_filter = PNG_FILTER_NONE; + else png_ptr->do_filter = PNG_ALL_FILTERS; } @@ -561,33 +582,43 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, { if (png_ptr->do_filter != PNG_FILTER_NONE) png_ptr->zlib_strategy = Z_FILTERED; + else png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; } if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) png_ptr->zlib_mem_level = 8; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) png_ptr->zlib_window_bits = 15; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) png_ptr->zlib_method = 8; + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, png_ptr->zlib_method, png_ptr->zlib_window_bits, png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + if (ret != Z_OK) { if (ret == Z_VERSION_ERROR) png_error(png_ptr, "zlib failed to initialize compressor -- version error"); + if (ret == Z_STREAM_ERROR) png_error(png_ptr, "zlib failed to initialize compressor -- stream error"); + if (ret == Z_MEM_ERROR) png_error(png_ptr, "zlib failed to initialize compressor -- mem error"); + png_error(png_ptr, "zlib failed to initialize compressor"); } + png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; /* libpng is not interested in zstream.data_type */ @@ -621,6 +652,7 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) { png_error(png_ptr, "Invalid number of colors in palette"); } + else { png_warning(png_ptr, "Invalid number of colors in palette"); @@ -632,6 +664,7 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) { png_warning(png_ptr, "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; } @@ -641,6 +674,7 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, (png_uint_32)(num_pal * 3)); #ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) { buf[0] = pal_ptr->red; @@ -648,11 +682,13 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) buf[2] = pal_ptr->blue; png_write_chunk_data(png_ptr, buf, (png_size_t)3); } + #else /* This is a little slower but some buggy compilers need to do this * instead */ pal_ptr=palette; + for (i = 0; i < num_pal; i++) { buf[0] = pal_ptr[i].red; @@ -660,6 +696,7 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) buf[2] = pal_ptr[i].blue; png_write_chunk_data(png_ptr, buf, (png_size_t)3); } + #endif png_write_chunk_end(png_ptr); png_ptr->mode |= PNG_HAVE_PLTE; @@ -709,6 +746,7 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) } } } + else png_error(png_ptr, "Invalid zlib compression method or flags in IDAT"); @@ -726,8 +764,7 @@ png_write_IEND(png_structp png_ptr) png_debug(1, "in png_write_IEND"); - png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, - (png_size_t)0); + png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, (png_size_t)0); png_ptr->mode |= PNG_HAVE_IEND; } @@ -778,6 +815,7 @@ png_write_sRGB(png_structp png_ptr, int srgb_intent) if (srgb_intent >= PNG_sRGB_INTENT_LAST) png_warning(png_ptr, "Invalid sRGB rendering intent specified"); + buf[0]=(png_byte)srgb_intent; png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); } @@ -803,8 +841,7 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, comp.input = NULL; comp.input_len = 0; - if ((name_len = png_check_keyword(png_ptr, name, - &new_name)) == 0) + if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0) return; if (compression_type != PNG_COMPRESSION_TYPE_BASE) @@ -850,7 +887,9 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, /* Make sure we include the NULL after the name and the compression type */ png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, (png_uint_32)(name_len + profile_len + 2)); + new_name[name_len + 1] = 0x00; + png_write_chunk_data(png_ptr, (png_bytep)new_name, (png_size_t)(name_len + 2)); @@ -886,8 +925,10 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) /* Make sure we include the NULL after the name */ png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, (png_uint_32)(name_len + 2 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1); /* Loop through each palette entry, writing appropriately */ @@ -902,6 +943,7 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) entrybuf[3] = (png_byte)ep->alpha; png_save_uint_16(entrybuf + 4, ep->frequency); } + else { png_save_uint_16(entrybuf + 0, ep->red); @@ -924,6 +966,7 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) entrybuf[3] = (png_byte)ep[i].alpha; png_save_uint_16(entrybuf + 4, ep[i].frequency); } + else { png_save_uint_16(entrybuf + 0, ep[i].red); @@ -959,6 +1002,7 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || sbit->green == 0 || sbit->green > maxbits || sbit->blue == 0 || sbit->blue > maxbits) @@ -966,11 +1010,13 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) png_warning(png_ptr, "Invalid sBIT depth specified"); return; } + buf[0] = sbit->red; buf[1] = sbit->green; buf[2] = sbit->blue; size = 3; } + else { if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) @@ -1098,10 +1144,12 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans_alpha, png_color_16p tran, png_warning(png_ptr, "Invalid number of transparent colors specified"); return; } + /* Write the chunk out as it is */ png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans_alpha, (png_size_t)num_trans); } + else if (color_type == PNG_COLOR_TYPE_GRAY) { /* One 16 bit value */ @@ -1114,6 +1162,7 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans_alpha, png_color_16p tran, png_save_uint_16(buf, tran->gray); png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); } + else if (color_type == PNG_COLOR_TYPE_RGB) { /* Three 16 bit values */ @@ -1128,6 +1177,7 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans_alpha, png_color_16p tran, } png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); } + else { png_warning(png_ptr, "Can't write tRNS with an alpha channel"); @@ -1157,9 +1207,11 @@ png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) png_warning(png_ptr, "Invalid background palette index"); return; } + buf[0] = back->index; png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); } + else if (color_type & PNG_COLOR_MASK_COLOR) { png_save_uint_16(buf, back->red); @@ -1169,16 +1221,19 @@ png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) { png_warning(png_ptr, "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + return; } png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); } + else { if (back->gray >= (1 << png_ptr->bit_depth)) { png_warning(png_ptr, "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + return; } png_save_uint_16(buf, back->gray); @@ -1202,6 +1257,7 @@ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) { png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); return; } @@ -1250,6 +1306,7 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) png_debug1(2, "Keyword to be checked is '%s'", key); *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + if (*new_key == NULL) { png_warning(png_ptr, "Out of memory while procesing keyword"); @@ -1273,6 +1330,7 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) #endif *dp = ' '; } + else { *dp = *kp; @@ -1316,11 +1374,13 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) *(dp++) = *kp; kflag = 1; } + else if (*kp == ' ') { key_len--; kwarn = 1; } + else { *(dp++) = *kp; @@ -1365,6 +1425,7 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, if (text == NULL || *text == '\0') text_len = 0; + else text_len = png_strlen(text); @@ -1379,6 +1440,7 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, */ png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1)); + if (text_len) png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len); @@ -1429,14 +1491,18 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, /* Write start of chunk */ png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32)(key_len+text_len + 2)); + /* Write key */ png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1)); + png_free(png_ptr, new_key); buf[0] = (png_byte)compression; + /* Write compression */ png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* Write the compressed data */ png_write_compressed_data_out(png_ptr, &comp); @@ -1477,11 +1543,13 @@ png_write_iTXt(png_structp png_ptr, int compression, png_charp key, if (lang_key == NULL) lang_key_len = 0; + else lang_key_len = png_strlen(lang_key); if (text == NULL) text_len = 0; + else text_len = png_strlen(text); @@ -1513,20 +1581,26 @@ png_write_iTXt(png_structp png_ptr, int compression, png_charp key, if (compression == PNG_ITXT_COMPRESSION_NONE || compression == PNG_TEXT_COMPRESSION_NONE) cbuf[0] = 0; + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ cbuf[0] = 1; + /* Set the compression method */ cbuf[1] = 0; + png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); cbuf[0] = 0; png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), (png_size_t)(lang_len + 1)); + png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), (png_size_t)(lang_key_len + 1)); + png_write_compressed_data_out(png_ptr, &comp); png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); png_free(png_ptr, new_lang); } @@ -1651,6 +1725,7 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, wlen = png_strlen(width); hlen = png_strlen(height); total_len = wlen + hlen + 2; + if (total_len > 64) { png_warning(png_ptr, "Can't write sCAL (buffer too small)"); @@ -1752,6 +1827,7 @@ png_write_start_row(png_structp png_ptr) /* Set up row buffer */ png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)buf_size); + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; #ifdef PNG_WRITE_FILTER_SUPPORTED @@ -1760,6 +1836,7 @@ png_write_start_row(png_structp png_ptr) { png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; } @@ -1774,6 +1851,7 @@ png_write_start_row(png_structp png_ptr) { png_ptr->up_row = (png_bytep)png_malloc(png_ptr, (png_size_t)(png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; } @@ -1781,6 +1859,7 @@ png_write_start_row(png_structp png_ptr) { png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; } @@ -1788,6 +1867,7 @@ png_write_start_row(png_structp png_ptr) { png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, (png_size_t)(png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; } } @@ -1801,21 +1881,25 @@ png_write_start_row(png_structp png_ptr) { png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - png_pass_start[0]) / png_pass_inc[0]; } + else { png_ptr->num_rows = png_ptr->height; png_ptr->usr_width = png_ptr->width; } } + else #endif { png_ptr->num_rows = png_ptr->height; png_ptr->usr_width = png_ptr->width; } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream.next_out = png_ptr->zbuf; } @@ -1860,24 +1944,30 @@ png_write_finish_row(png_structp png_ptr) { png_ptr->pass++; } + else { /* Loop until we find a non-zero width or height pass */ do { png_ptr->pass++; + if (png_ptr->pass >= 7) break; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[png_ptr->pass] - 1 - png_pass_start[png_ptr->pass]) / png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[png_ptr->pass] - 1 - png_pass_ystart[png_ptr->pass]) / png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); } @@ -1889,6 +1979,7 @@ png_write_finish_row(png_structp png_ptr) png_memset(png_ptr->prev_row, 0, (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* png_ptr->usr_bit_depth, png_ptr->width)) + 1); + return; } } @@ -1900,6 +1991,7 @@ png_write_finish_row(png_structp png_ptr) { /* Tell the compressor we are done */ ret = deflate(&png_ptr->zstream, Z_FINISH); + /* Check for an error */ if (ret == Z_OK) { @@ -1911,6 +2003,7 @@ png_write_finish_row(png_structp png_ptr) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } } + else if (ret != Z_STREAM_END) { if (png_ptr->zstream.msg != NULL) @@ -1984,12 +2077,14 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) *dp++ = (png_byte)d; d = 0; } + else shift--; } if (shift != 7) *dp = (png_byte)d; + break; } case 2: @@ -2005,6 +2100,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) dp = row; shift = 6; d = 0; + for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { @@ -2018,11 +2114,13 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) *dp++ = (png_byte)d; d = 0; } + else shift -= 2; } if (shift != 6) - *dp = (png_byte)d; + *dp = (png_byte)d; + break; } case 4: @@ -2080,6 +2178,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) /* Move the pixel */ if (dp != sp) png_memcpy(dp, sp, pixel_bytes); + /* Next pixel */ dp += pixel_bytes; } @@ -2091,6 +2190,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) png_pass_inc[pass] - 1 - png_pass_start[pass]) / png_pass_inc[pass]; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width); } @@ -2191,6 +2291,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { sumlo = (sumlo * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2202,11 +2303,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) */ sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> PNG_COST_SHIFT; if (sumhi > PNG_HIMASK) sum = PNG_MAXSUM; + else sum = (sumhi << PNG_HISHIFT) + sumlo; } @@ -2220,16 +2323,19 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { png_bytep rp, lp, dp; png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; i++, rp++, dp++) { *dp = *rp; } + for (lp = row_buf + 1; i < row_bytes; i++, rp++, lp++, dp++) { *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); } + best_row = png_ptr->sub_row; } @@ -2258,6 +2364,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2265,11 +2372,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> PNG_COST_SHIFT; if (lmhi > PNG_HIMASK) lmins = PNG_MAXSUM; + else lmins = (lmhi << PNG_HISHIFT) + lmlo; } @@ -2307,6 +2416,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2314,11 +2424,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> PNG_COST_SHIFT; if (sumhi > PNG_HIMASK) sum = PNG_MAXSUM; + else sum = (sumhi << PNG_HISHIFT) + sumlo; } @@ -2368,6 +2480,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2375,11 +2488,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> PNG_COST_SHIFT; if (lmhi > PNG_HIMASK) lmins = PNG_MAXSUM; + else lmins = (lmhi << PNG_HISHIFT) + lmlo; } @@ -2410,6 +2525,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { sumlo = (sumlo * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2417,11 +2533,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> PNG_COST_SHIFT; if (sumhi > PNG_HIMASK) sum = PNG_MAXSUM; + else sum = (sumhi << PNG_HISHIFT) + sumlo; } @@ -2439,11 +2557,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { png_bytep rp, dp, pp, lp; png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, pp = prev_row + 1; i < bpp; i++) { *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); } + for (lp = row_buf + 1; i < row_bytes; i++) { *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) @@ -2473,6 +2593,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2480,11 +2601,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> PNG_COST_SHIFT; if (lmhi > PNG_HIMASK) lmins = PNG_MAXSUM; + else lmins = (lmhi << PNG_HISHIFT) + lmlo; } @@ -2497,6 +2620,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) sum += (v < 128) ? v : 256 - v; } + for (lp = row_buf + 1; i < row_bytes; i++) { v = *dp++ = @@ -2522,6 +2646,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { sumlo = (sumlo * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2529,11 +2654,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> PNG_COST_SHIFT; if (sumhi > PNG_HIMASK) sum = PNG_MAXSUM; + else sum = (sumhi << PNG_HISHIFT) + sumlo; } @@ -2551,6 +2678,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { png_bytep rp, dp, pp, cp, lp; png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, pp = prev_row + 1; i < bpp; i++) { @@ -2606,6 +2734,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2613,11 +2742,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> PNG_COST_SHIFT; if (lmhi > PNG_HIMASK) lmins = PNG_MAXSUM; + else lmins = (lmhi << PNG_HISHIFT) + lmlo; } @@ -2687,6 +2818,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { sumlo = (sumlo * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> PNG_WEIGHT_SHIFT; } @@ -2694,11 +2826,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> PNG_COST_SHIFT; if (sumhi > PNG_HIMASK) sum = PNG_MAXSUM; + else sum = (sumhi << PNG_HISHIFT) + sumlo; } @@ -2720,6 +2854,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) if (png_ptr->num_prev_filters > 0) { int j; + for (j = 1; j < num_p_filters; j++) { png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; @@ -2749,11 +2884,13 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) /* Compress the data */ ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + /* Check for compression errors */ if (ret != Z_OK) { if (png_ptr->zstream.msg != NULL) png_error(png_ptr, png_ptr->zstream.msg); + else png_error(png_ptr, "zlib error"); }