diff --git a/pngrutil.c b/pngrutil.c index 85a5379b2..56e216ed6 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -1044,6 +1044,7 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) return; intent = buf[0]; + /* Check for bad intent */ if (intent >= PNG_sRGB_INTENT_LAST) { @@ -1162,6 +1163,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Compression_type should always be zero */ compression_type = *profile++; + if (compression_type) { png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); @@ -1253,6 +1255,7 @@ png_handle_sPLT(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 sPLT"); @@ -1343,6 +1346,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } new_palette.nentries = (png_int_32)(data_length / entry_size); + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); @@ -1377,6 +1381,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } #else pp = new_palette.entries; + for (i = 0; i < new_palette.nentries; i++) { @@ -1421,6 +1426,7 @@ png_handle_tRNS(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 tRNS"); + else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid tRNS after IDAT"); @@ -1461,6 +1467,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + png_crc_read(png_ptr, buf, (png_size_t)length); png_ptr->num_trans = 1; png_ptr->trans_color.red = png_get_uint_16(buf); @@ -1475,6 +1482,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Should be an error, but we can cope with it. */ png_warning(png_ptr, "Missing PLTE before tRNS"); } + if (length > (png_uint_32)png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH) { @@ -1482,12 +1490,14 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } + if (length == 0) { png_warning(png_ptr, "Zero length tRNS chunk"); png_crc_finish(png_ptr, length); return; } + png_crc_read(png_ptr, readbuf, (png_size_t)length); png_ptr->num_trans = (png_uint_16)length; } @@ -1573,6 +1583,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { png_ptr->background.index = buf[0]; + if (info_ptr && info_ptr->num_palette) { if (buf[0] >= info_ptr->num_palette) @@ -1645,6 +1656,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } num = length / 2 ; + if (num != (unsigned int)png_ptr->num_palette || num > (unsigned int)PNG_MAX_PALETTE_LENGTH) { @@ -1862,8 +1874,10 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Empty loop to move past the units string. */ ; png_debug(3, "Allocating pCAL parameters array"); + params = (png_charpp)png_malloc_warn(png_ptr, (png_size_t)(nparams * png_sizeof(png_charp))); + if (params == NULL) { png_free(png_ptr, png_ptr->chunkdata); @@ -1878,6 +1892,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) buf++; /* Skip the null string terminator from previous parameter. */ png_debug1(3, "Reading pCAL parameter %d", i); + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) /* Empty loop to move past each parameter string */ ; @@ -1930,6 +1945,7 @@ 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) @@ -1964,17 +1980,21 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) */ index = 0; state = 0; + if (png_ptr->chunkdata[1] == 45 /* negative width */ || !png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) || index >= slength || png_ptr->chunkdata[index++] != 0) png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format"); + else { png_size_t heighti = index; + if (png_ptr->chunkdata[index] == 45 /* negative height */ || !png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) || index != slength) png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); + else /* This is the (only) success case. */ png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], @@ -2082,11 +2102,13 @@ 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 = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) { png_warning(png_ptr, "No memory to process text chunk"); return; } + slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); @@ -2188,6 +2210,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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, "Out of memory processing zTXt chunk"); @@ -2221,11 +2244,13 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) else { comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) { png_warning(png_ptr, "Unknown compression type in zTXt chunk"); comp_type = PNG_TEXT_COMPRESSION_zTXt; } + text++; /* Skip the compression_method byte */ } @@ -2316,11 +2341,13 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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 to process iTXt chunk"); return; } + slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); @@ -2458,6 +2485,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->mode & PNG_HAVE_IDAT) { PNG_IDAT; + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ png_ptr->mode |= PNG_AFTER_IDAT; } @@ -2494,8 +2522,10 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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) @@ -2512,6 +2542,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { /* Callback to user unknown chunk handler */ int ret; + ret = (*(png_ptr->read_user_chunk_fn)) (png_ptr, &png_ptr->unknown_chunk); @@ -2521,11 +2552,13 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (ret == 0) { if (!(png_ptr->chunk_name[0] & 0x20)) + { #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != 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); @@ -2655,6 +2688,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) } break; } + case 2: { png_bytep sp = png_ptr->row_buf + 1; @@ -2711,6 +2745,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) } break; } + case 4: { png_bytep sp = png_ptr->row_buf + 1; @@ -2766,6 +2801,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) } break; } + default: { png_bytep sp = png_ptr->row_buf + 1; @@ -2775,7 +2811,6 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) png_uint_32 row_width = png_ptr->width; png_byte m = 0x80; - for (i = 0; i < row_width; i++) { if (m & mask) @@ -2879,6 +2914,7 @@ png_do_read_interlace(png_structp png_ptr) } break; } + case 2: { png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); @@ -2940,6 +2976,7 @@ png_do_read_interlace(png_structp png_ptr) } break; } + case 4: { png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); @@ -3003,8 +3040,10 @@ png_do_read_interlace(png_structp png_ptr) default: { png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; int jstop = png_pass_inc[pass]; @@ -3090,6 +3129,7 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, { *rp = (png_byte)(((int)(*rp) + ((int)(*pp++) / 2 )) & 0xff); + rp++; } @@ -3097,6 +3137,7 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, { *rp = (png_byte)(((int)(*rp) + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; } break; @@ -3220,6 +3261,7 @@ png_read_finish_row(png_structp png_ptr) else /* if (png_ptr->transformations & PNG_INTERLACE) */ break; + } while (png_ptr->iwidth == 0); if (png_ptr->pass < 7) @@ -3333,6 +3375,7 @@ png_read_start_row(png_structp png_ptr) if (!(png_ptr->transformations & PNG_INTERLACE)) png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - png_pass_ystart[0]) / png_pass_yinc[0]; + else png_ptr->num_rows = png_ptr->height; @@ -3372,6 +3415,7 @@ png_read_start_row(png_structp png_ptr) { if (max_pixel_depth < 8) max_pixel_depth = 8; + if (png_ptr->num_trans) max_pixel_depth *= 2; } @@ -3442,6 +3486,7 @@ png_read_start_row(png_structp png_ptr) else max_pixel_depth = 24; } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) max_pixel_depth = 64; @@ -3457,6 +3502,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) { int user_pixel_depth = png_ptr->user_transform_depth* png_ptr->user_transform_channels; + if (user_pixel_depth > max_pixel_depth) max_pixel_depth=user_pixel_depth; } @@ -3544,6 +3590,7 @@ png_get_num_passes(png_structp png_ptr) { if (png_ptr->interlaced) return 7; + else return 1; } @@ -3559,6 +3606,7 @@ png_get_num_rows(png_structp png_ptr) { if (png_ptr->flags & PNG_FLAG_ROW_INIT) return png_ptr->num_rows; + else png_error(png_ptr, "Call png_start_read_image or png_read_update_info " "before png_get_num_rows"); diff --git a/pngwtran.c b/pngwtran.c index 8eff5e7e8..066e1e2c9 100644 --- a/pngwtran.c +++ b/pngwtran.c @@ -29,17 +29,17 @@ png_do_write_transformations(png_structp png_ptr) #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED if (png_ptr->transformations & PNG_USER_TRANSFORM) if (png_ptr->write_user_transform_fn != NULL) - (*(png_ptr->write_user_transform_fn)) /* User write transform + (*(png_ptr->write_user_transform_fn)) /* User write transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* 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 @@ -142,6 +142,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) break; } + case 2: { png_bytep sp, dp; @@ -180,6 +181,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) break; } + case 4: { png_bytep sp, dp; @@ -219,6 +221,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) break; } } + row_info->bit_depth = (png_byte)bit_depth; row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, @@ -310,6 +313,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, } } } + else if (row_info->bit_depth == 8) { png_bytep bp = row; @@ -336,6 +340,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, } } } + else { png_bytep bp; diff --git a/pngwutil.c b/pngwutil.c index bb8a0252b..454350c70 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -97,6 +97,7 @@ png_write_chunk(png_structp png_ptr, png_const_bytep chunk_name, { if (png_ptr == NULL) return; + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); png_write_chunk_data(png_ptr, data, (png_size_t)length); png_write_chunk_end(png_ptr); @@ -129,10 +130,13 @@ png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name, png_save_uint_32(buf, length); png_memcpy(buf + 4, chunk_name, 4); png_write_data(png_ptr, buf, (png_size_t)8); + /* Put the chunk name into png_ptr->chunk_name */ png_memcpy(png_ptr->chunk_name, chunk_name, 4); + /* Reset the crc and run it over the chunk name */ png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, chunk_name, 4); #ifdef PNG_IO_STATE_SUPPORTED @@ -159,6 +163,7 @@ png_write_chunk_data(png_structp png_ptr, png_const_bytep data, if (data != NULL && length > 0) { png_write_data(png_ptr, data, length); + /* Update the CRC after writing the data, * in case that the user I/O routine alters it. */ @@ -197,10 +202,10 @@ png_write_chunk_end(png_structp png_ptr) typedef struct { png_const_bytep input; /* The uncompressed input data */ - png_size_t input_len; /* Its length */ - int num_output_ptr; /* Number of output pointers used */ - int max_output_ptr; /* Size of output_ptr */ - png_bytep *output_ptr; /* Array of pointers to output */ + png_size_t input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_bytep *output_ptr; /* Array of pointers to output */ } compression_state; /* Compress given text into storage in the png_ptr structure */ @@ -268,6 +273,7 @@ png_text_compress(png_structp png_ptr, /* Error */ if (png_ptr->zstream.msg != NULL) png_error(png_ptr, png_ptr->zstream.msg); + else png_error(png_ptr, "zlib error"); } @@ -287,11 +293,14 @@ png_text_compress(png_structp png_ptr, png_bytepp old_ptr; old_ptr = comp->output_ptr; + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, (png_alloc_size_t) (comp->max_output_ptr * png_sizeof(png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); } else @@ -304,8 +313,10 @@ png_text_compress(png_structp png_ptr, comp->output_ptr[comp->num_output_ptr] = (png_bytep)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 */ @@ -338,12 +349,15 @@ png_text_compress(png_structp png_ptr, png_bytepp old_ptr; old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ comp->output_ptr = (png_bytepp)png_malloc(png_ptr, (png_alloc_size_t)(comp->max_output_ptr * png_sizeof(png_charp))); + png_memcpy(comp->output_ptr, old_ptr, old_max * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); } @@ -381,6 +395,7 @@ png_text_compress(png_structp png_ptr, /* Text length is number of buffers plus last buffer */ text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; @@ -409,6 +424,7 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) png_free(png_ptr, comp->output_ptr[i]); } + if (comp->max_output_ptr != 0) png_free(png_ptr, comp->output_ptr); @@ -453,6 +469,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, case 16: #endif png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for grayscale image"); @@ -479,6 +496,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); } @@ -590,6 +608,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, else png_ptr->do_filter = PNG_ALL_FILTERS; } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) { if (png_ptr->do_filter != PNG_FILTER_NONE) @@ -598,6 +617,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, else png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; @@ -633,8 +653,9 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, 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 */ - /* Set it to a predefined value, to avoid its evaluation inside zlib */ + /* libpng is not interested in zstream.data_type, so set it + * to a predefined value, to avoid its evaluation inside zlib + */ png_ptr->zstream.data_type = Z_BINARY; png_ptr->mode = PNG_HAVE_IHDR; @@ -749,7 +770,9 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) z_cinfo--; half_z_window_size >>= 1; } + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + if (data[0] != z_cmf) { int tmp; @@ -857,6 +880,7 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, { png_warning(png_ptr, "Embedded profile length in iCCP chunk is negative"); + png_free(png_ptr, new_name); return; } @@ -865,6 +889,7 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, { png_warning(png_ptr, "Embedded profile length too large in iCCP chunk"); + png_free(png_ptr, new_name); return; } @@ -873,6 +898,7 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, { png_warning(png_ptr, "Truncating profile to actual length in iCCP chunk"); + profile_len = embedded_profile_len; } @@ -948,6 +974,7 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette) png_save_uint_16(entrybuf + 6, ep->alpha); png_save_uint_16(entrybuf + 8, ep->frequency); } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); } #else @@ -971,6 +998,7 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette) png_save_uint_16(entrybuf + 6, ep[i].alpha); png_save_uint_16(entrybuf + 8, ep[i].frequency); } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); } #endif @@ -1020,6 +1048,7 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type) png_warning(png_ptr, "Invalid sBIT depth specified"); return; } + buf[0] = sbit->gray; size = 1; } @@ -1031,6 +1060,7 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type) png_warning(png_ptr, "Invalid sBIT depth specified"); return; } + buf[size++] = sbit->alpha; } @@ -1104,8 +1134,10 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, { png_warning(png_ptr, "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + return; } + png_save_uint_16(buf, tran->gray); png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); } @@ -1126,6 +1158,7 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); return; } + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); } @@ -1179,6 +1212,7 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type) return; } + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); } @@ -1191,6 +1225,7 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type) return; } + png_save_uint_16(buf, back->gray); png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); } @@ -1218,11 +1253,13 @@ png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist) } png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); + for (i = 0; i < num_hist; i++) { png_save_uint_16(buf, hist[i]); png_write_chunk_data(png_ptr, buf, (png_size_t)2); } + png_write_chunk_end(png_ptr); } #endif @@ -1386,7 +1423,7 @@ png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text, /* Make sure we include the 0 after the key */ png_write_chunk_start(png_ptr, png_tEXt, - (png_uint_32)(key_len + text_len + 1)); + (png_uint_32)(key_len + text_len + 1)); /* * We leave it to the application to meet PNG-1.0 requirements on the * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of @@ -1394,11 +1431,11 @@ png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text, * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. */ png_write_chunk_data(png_ptr, (png_bytep)new_key, - (png_size_t)(key_len + 1)); + (png_size_t)(key_len + 1)); if (text_len) png_write_chunk_data(png_ptr, (png_const_bytep)text, - (png_size_t)text_len); + (png_size_t)text_len); png_write_chunk_end(png_ptr); png_free(png_ptr, new_key); @@ -1511,11 +1548,12 @@ png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key, /* Compute the compressed data; do it now for the length */ text_len = png_text_compress(png_ptr, text, text_len, compression - 2, - &comp); + &comp); /* Make sure we include the compression flag, the compression byte, - * and the NULs after the key, lang, and lang_key parts */ + * and the NULs after the key, lang, and lang_key parts + */ png_write_chunk_start(png_ptr, png_iTXt, (png_uint_32)( 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ @@ -1534,10 +1572,10 @@ png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key, /* Set the compression flag */ if (compression == PNG_ITXT_COMPRESSION_NONE || compression == PNG_TEXT_COMPRESSION_NONE) - cbuf[0] = 0; + cbuf[0] = 0; else /* compression == PNG_ITXT_COMPRESSION_zTXt */ - cbuf[0] = 1; + cbuf[0] = 1; /* Set the compression method */ cbuf[1] = 0; @@ -1546,10 +1584,10 @@ png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key, cbuf[0] = 0; png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf), - (png_size_t)(lang_len + 1)); + (png_size_t)(lang_len + 1)); png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf), - (png_size_t)(lang_key_len + 1)); + (png_size_t)(lang_key_len + 1)); png_write_compressed_data_out(png_ptr, &comp); @@ -1585,8 +1623,8 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, /* Write the pCAL chunk (described in the PNG extensions document) */ void /* PRIVATE */ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, - png_int_32 X1, int type, int nparams, png_const_charp units, - png_charpp params) + png_int_32 X1, int type, int nparams, png_const_charp units, + png_charpp params) { PNG_pCAL; png_size_t purpose_len, units_len, total_len; @@ -1996,6 +2034,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) dp = row; d = 0; shift = 7; + for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { @@ -2083,11 +2122,13 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) *dp++ = (png_byte)d; d = 0; } + else shift -= 4; } if (shift != 4) *dp = (png_byte)d; + break; } @@ -2101,6 +2142,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) /* Start at the beginning */ dp = row; + /* Find out how many bytes each pixel takes up */ pixel_bytes = (row_info->pixel_depth >> 3); @@ -2110,6 +2152,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { /* Find out where the original pixel is */ sp = row + (png_size_t)i * pixel_bytes; + /* Move the pixel */ if (dp != sp) png_memcpy(dp, sp, pixel_bytes); @@ -2185,11 +2228,14 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) * computationally expensive). * * GRR 980525: consider also + * * (1) minimum sum of absolute differences from running average (i.e., * keep running sum of non-absolute differences & count of bytes) * [track dispersion, too? restart average if dispersion too large?] + * * (1b) minimum sum of absolute differences from sliding average, probably * with window size <= deflate window (usually 32K) + * * (2) minimum sum of squared differences from zero or running average * (i.e., ~ root-mean-square approach) */ @@ -2391,6 +2437,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); } + best_row = png_ptr->up_row; } @@ -2724,10 +2771,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) pa = abs(p - a); pb = abs(p - b); pc = abs(p - c); + if (pa <= pb && pa <= pc) p = a; + else if (pb <= pc) p = b; + else p = c; #endif /* PNG_SLOW_PAETH */ @@ -2795,6 +2845,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) { png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; } + png_ptr->prev_filters[j] = best_row[0]; } #endif