From 30e525feb63dd5917392f42eb63f67ca043dad50 Mon Sep 17 00:00:00 2001 From: "pavlov@pavlov.net" Date: Thu, 19 Apr 2007 13:40:53 -0700 Subject: [PATCH] various small fixes for APNG. bug 257197. patch from asmith15@learn.senecac.on.ca. r=me --- modules/libimg/png/MOZCHANGES | 2 ++ modules/libimg/png/png.h | 21 ++++++++------ modules/libimg/png/pngget.c | 20 ++++++------- modules/libimg/png/pngpread.c | 3 ++ modules/libimg/png/pngread.c | 3 ++ modules/libimg/png/pngrutil.c | 24 ++++++++------- modules/libimg/png/pngset.c | 29 +++++++++++++++---- modules/libimg/png/pngwrite.c | 7 +++-- modules/libimg/png/pngwutil.c | 19 +++++------- modules/libpr0n/decoders/png/nsPNGDecoder.cpp | 11 +++---- 10 files changed, 80 insertions(+), 59 deletions(-) diff --git a/modules/libimg/png/MOZCHANGES b/modules/libimg/png/MOZCHANGES index 718b0f709fb8..78e592f979b6 100644 --- a/modules/libimg/png/MOZCHANGES +++ b/modules/libimg/png/MOZCHANGES @@ -1,6 +1,8 @@ Changes made to pristine png source by mozilla.org developers. +2007/03/20 -- Added support for APNG + 2006/06/27 -- Synced with libpng-1.2.12 tree 2004/10/07 -- Synced with libpng-1.2.7 tree diff --git a/modules/libimg/png/png.h b/modules/libimg/png/png.h index 2a9f8ed5bf3e..6fa22fc4e34b 100644 --- a/modules/libimg/png/png.h +++ b/modules/libimg/png/png.h @@ -918,8 +918,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #endif #if defined(PNG_APNG_SUPPORTED) - png_uint_32 num_frames; - png_uint_32 num_iterations; + png_uint_32 num_frames; /* including default image */ + png_uint_32 num_plays; png_uint_32 next_frame_width; png_uint_32 next_frame_height; png_uint_32 next_frame_x_offset; @@ -1424,7 +1424,7 @@ struct png_struct_def #endif #if defined(PNG_WRITE_APNG_SUPPORTED) - png_uint_32 num_frames_to_write; /* copy of info_ptr->num_frames */ + png_uint_32 num_frames_to_write; png_uint_32 num_frames_written; #endif @@ -1766,7 +1766,7 @@ extern PNG_EXPORT (void,png_write_frame_head) PNGARG((png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, - png_byte blend_op, png_byte first_frame_hidden)); + png_byte blend_op)); extern PNG_EXPORT (void,png_write_frame_tail) PNGARG((png_structp png_ptr, png_infop png_info)); @@ -2455,12 +2455,12 @@ extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, #if defined(PNG_APNG_SUPPORTED) extern PNG_EXPORT(png_uint_32,png_get_acTL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_iterations)); + png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays)); extern PNG_EXPORT(png_uint_32,png_set_acTL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_iterations)); + png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays)); extern PNG_EXPORT(png_uint_32,png_get_num_frames) PNGARG((png_structp png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32,png_get_num_iterations) +extern PNG_EXPORT(png_uint_32,png_get_num_plays) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_uint_32,png_get_next_frame_fcTL) @@ -2495,8 +2495,10 @@ extern PNG_EXPORT(png_byte,png_get_next_frame_dispose_op) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_byte,png_get_next_frame_blend_op) PNGARG((png_structp png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_byte,png_first_frame_is_hidden) +extern PNG_EXPORT(png_byte,png_get_first_frame_is_hidden) PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32,png_set_first_frame_is_hidden) + PNGARG((png_structp png_ptr, png_infop info_ptr, png_byte is_hidden)); #endif /* PNG_APNG_SUPPORTED */ #if defined(PNG_READ_APNG_SUPPORTED) @@ -3259,7 +3261,7 @@ PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, #if defined(PNG_WRITE_APNG_SUPPORTED) PNG_EXTERN void png_write_acTL PNGARG((png_structp png_ptr, - png_uint_32 num_frames, png_uint_32 num_iterations)); + png_uint_32 num_frames, png_uint_32 num_plays)); PNG_EXTERN void png_write_fcTL PNGARG((png_structp png_ptr, png_uint_32 width, png_uint_32 height, @@ -3553,6 +3555,7 @@ PNG_EXTERN void png_handle_acTL PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); PNG_EXTERN void png_handle_fcTL PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_have_info PNGARG((png_structp png_ptr, png_infop info_ptr)); PNG_EXTERN void png_handle_fdAT PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); PNG_EXTERN void png_ensure_sequence_number PNGARG((png_structp png_ptr, diff --git a/modules/libimg/png/pngget.c b/modules/libimg/png/pngget.c index 65afe83108ae..f39de9307660 100644 --- a/modules/libimg/png/pngget.c +++ b/modules/libimg/png/pngget.c @@ -797,16 +797,16 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr, #if defined(PNG_APNG_SUPPORTED) png_uint_32 PNGAPI png_get_acTL(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *num_frames, png_uint_32 *num_iterations) + png_uint_32 *num_frames, png_uint_32 *num_plays) { png_debug1(1, "in %s retrieval function\n", "acTL"); if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_acTL) && - num_frames != NULL && num_iterations != NULL) + num_frames != NULL && num_plays != NULL) { *num_frames = info_ptr->num_frames; - *num_iterations = info_ptr->num_iterations; + *num_plays = info_ptr->num_plays; return (1); } @@ -824,12 +824,12 @@ png_get_num_frames(png_structp png_ptr, png_infop info_ptr) } png_uint_32 PNGAPI -png_get_num_iterations(png_structp png_ptr, png_infop info_ptr) +png_get_num_plays(png_structp png_ptr, png_infop info_ptr) { - png_debug(1, "in png_get_num_iterations()\n"); + png_debug(1, "in png_get_num_plays()\n"); if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->num_iterations); + return (info_ptr->num_plays); return (0); } @@ -944,14 +944,12 @@ png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr) } png_byte PNGAPI -png_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr) +png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_first_frame_is_hidden()\n"); - if (png_ptr != NULL && info_ptr != NULL && - info_ptr->valid & PNG_INFO_acTL && - !(info_ptr->valid & PNG_INFO_fcTL)) - return 1; + if (png_ptr != NULL) + return png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN; return 0; } diff --git a/modules/libimg/png/pngpread.c b/modules/libimg/png/pngpread.c index 452f76def770..40987d47fe2d 100644 --- a/modules/libimg/png/pngpread.c +++ b/modules/libimg/png/pngpread.c @@ -397,6 +397,9 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) png_error(png_ptr, "Too many IDAT's found"); } +#if defined(PNG_READ_APNG_SUPPORTED) + png_have_info(png_ptr, info_ptr); +#endif png_ptr->idat_size = png_ptr->push_length; png_ptr->mode |= PNG_HAVE_IDAT; png_ptr->process_mode = PNG_READ_IDAT_MODE; diff --git a/modules/libimg/png/pngread.c b/modules/libimg/png/pngread.c index b9e3f890f065..2285f46ab233 100644 --- a/modules/libimg/png/pngread.c +++ b/modules/libimg/png/pngread.c @@ -459,6 +459,9 @@ png_read_info(png_structp png_ptr, png_infop info_ptr) !(png_ptr->mode & PNG_HAVE_PLTE)) png_error(png_ptr, "Missing PLTE before IDAT"); +#if defined(PNG_READ_APNG_SUPPORTED) + png_have_info(png_ptr, info_ptr); +#endif png_ptr->idat_size = length; png_ptr->mode |= PNG_HAVE_IDAT; break; diff --git a/modules/libimg/png/pngrutil.c b/modules/libimg/png/pngrutil.c index 7350e2fb0b0c..c547e0d35983 100644 --- a/modules/libimg/png/pngrutil.c +++ b/modules/libimg/png/pngrutil.c @@ -2144,7 +2144,7 @@ png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_byte data[8]; png_uint_32 num_frames; - png_uint_32 num_iterations; + png_uint_32 num_plays; png_uint_32 didSet; png_debug(1, "in png_handle_acTL\n"); @@ -2176,18 +2176,12 @@ png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, 0); num_frames = png_get_uint_31(png_ptr, data); - num_iterations = png_get_uint_31(png_ptr, data + 4); + num_plays = png_get_uint_31(png_ptr, data + 4); /* the set function will do error checking on num_frames */ - didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_iterations); + didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays); if(didSet) - { png_ptr->mode |= PNG_HAVE_acTL; - - /* if there is an fcTL this flag will be unset in png_handle_fcTL() */ - if (num_frames > 1) - png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; - } } void /* PRIVATE */ @@ -2260,8 +2254,16 @@ png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_read_reinit(png_ptr, info_ptr); png_ptr->mode |= PNG_HAVE_fcTL; - - png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; +} + +void /* PRIVATE */ +png_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL)) + { + png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; + info_ptr->num_frames++; + } } void /* PRIVATE */ diff --git a/modules/libimg/png/pngset.c b/modules/libimg/png/pngset.c index 79ff540b5b23..208fb8022e1e 100644 --- a/modules/libimg/png/pngset.c +++ b/modules/libimg/png/pngset.c @@ -1001,7 +1001,7 @@ png_set_sPLT(png_structp png_ptr, #if defined(PNG_APNG_SUPPORTED) png_uint_32 PNGAPI png_set_acTL(png_structp png_ptr, png_infop info_ptr, - png_uint_32 num_frames, png_uint_32 num_iterations) + png_uint_32 num_frames, png_uint_32 num_plays) { png_debug1(1, "in %s storage function\n", "acTL"); @@ -1012,28 +1012,28 @@ png_set_acTL(png_structp png_ptr, png_infop info_ptr, "or info_ptr ignored"); return (0); } - if(num_frames == 0) + if (num_frames == 0) { png_warning(png_ptr, "Ignoring attempt to set acTL with num_frames zero"); return (0); } - if(num_frames > PNG_UINT_31_MAX) + if (num_frames > PNG_UINT_31_MAX) { png_warning(png_ptr, "Ignoring attempt to set acTL with num_frames > 2^31-1"); return (0); } - if(num_iterations > PNG_UINT_31_MAX) + if (num_plays > PNG_UINT_31_MAX) { png_warning(png_ptr, - "Ignoring attempt to set acTL with num_iterations " + "Ignoring attempt to set acTL with num_plays " "> 2^31-1"); return (0); } info_ptr->num_frames = num_frames; - info_ptr->num_iterations = num_iterations; + info_ptr->num_plays = num_plays; info_ptr->valid |= PNG_INFO_acTL; @@ -1114,6 +1114,23 @@ png_ensure_fcTL_is_valid(png_structp png_ptr, "color type 'truecolor without alpha'"); } } + +png_uint_32 PNGAPI +png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr, + png_byte is_hidden) +{ + png_debug(1, "in png_first_frame_is_hidden()\n"); + + if (png_ptr == NULL) + return 0; + + if(is_hidden) + png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; + else + png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; + + return 1; +} #endif /* PNG_APNG_SUPPORTED */ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) diff --git a/modules/libimg/png/pngwrite.c b/modules/libimg/png/pngwrite.c index c665b6766681..84b9d828cabb 100644 --- a/modules/libimg/png/pngwrite.c +++ b/modules/libimg/png/pngwrite.c @@ -263,7 +263,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) #endif #if defined(PNG_WRITE_APNG_SUPPORTED) if (info_ptr->valid & PNG_INFO_acTL) - png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_iterations); + png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) if (info_ptr->unknown_chunks_num) @@ -1530,7 +1530,7 @@ png_write_frame_head(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, - png_byte blend_op, png_byte first_frame_hidden) + png_byte blend_op) { png_debug(1, "in png_write_frame_head\n"); @@ -1543,7 +1543,8 @@ png_write_frame_head(png_structp png_ptr, png_infop info_ptr, png_write_reinit(png_ptr, info_ptr, width, height); - if ( !(png_ptr->num_frames_written == 0 && first_frame_hidden) ) + if ( !(png_ptr->num_frames_written == 0 && + (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) ) png_write_fcTL(png_ptr, width, height, x_offset, y_offset, delay_num, delay_den, dispose_op, blend_op); } diff --git a/modules/libimg/png/pngwutil.c b/modules/libimg/png/pngwutil.c index 7e433fe7b990..5d394bb6271f 100644 --- a/modules/libimg/png/pngwutil.c +++ b/modules/libimg/png/pngwutil.c @@ -1752,7 +1752,7 @@ png_write_tIME(png_structp png_ptr, png_timep mod_time) #if defined(PNG_WRITE_APNG_SUPPORTED) void /* PRIVATE */ png_write_acTL(png_structp png_ptr, - png_uint_32 num_frames, png_uint_32 num_iterations) + png_uint_32 num_frames, png_uint_32 num_plays) { #ifdef PNG_USE_LOCAL_ARRAYS PNG_acTL; @@ -1761,19 +1761,13 @@ png_write_acTL(png_structp png_ptr, png_debug(1, "in png_write_acTL\n"); - if (num_frames == 0) - png_error(png_ptr, "png_write_acTL: invalid number of frames (0)"); - if (num_frames > PNG_UINT_31_MAX) - png_error(png_ptr, "png_write_acTL: invalid number of frames " - "(> 2^31-1)"); - if (num_iterations > PNG_UINT_31_MAX) - png_error(png_ptr, "png_write_acTL: invalid number of iterations " - "(> 2^31-1)"); - png_ptr->num_frames_to_write = num_frames; + if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) + num_frames--; + png_save_uint_32(data, num_frames); - png_save_uint_32(data + 4, num_iterations); + png_save_uint_32(data + 4, num_plays); png_write_chunk(png_ptr, (png_bytep)png_acTL, data, (png_size_t)8); } @@ -1781,7 +1775,8 @@ png_write_acTL(png_structp png_ptr, void /* PRIVATE */ png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, png_byte blend_op) + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op) { #ifdef PNG_USE_LOCAL_ARRAYS PNG_fcTL; diff --git a/modules/libpr0n/decoders/png/nsPNGDecoder.cpp b/modules/libpr0n/decoders/png/nsPNGDecoder.cpp index 5084872ed1e9..5891f1c26bfe 100644 --- a/modules/libpr0n/decoders/png/nsPNGDecoder.cpp +++ b/modules/libpr0n/decoders/png/nsPNGDecoder.cpp @@ -381,7 +381,7 @@ info_callback(png_structp png_ptr, png_infop info_ptr) if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) png_set_progressive_frame_fn(png_ptr, frame_info_callback, NULL); - if (png_first_frame_is_hidden(png_ptr, info_ptr)) { + if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) { decoder->apngFlags |= FRAME_HIDDEN; // create a frame just to get bpr, to allocate interlacebuf @@ -409,7 +409,7 @@ info_callback(png_structp png_ptr, png_infop info_ptr) } } - if (png_first_frame_is_hidden(png_ptr, info_ptr)) + if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) decoder->mFrame = nsnull; return; @@ -557,11 +557,8 @@ end_callback(png_structp png_ptr, png_infop info_ptr) nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr)); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) { - PRInt32 num_iterations = png_get_num_iterations(png_ptr, info_ptr); - if (num_iterations <= 0) /* forever */ - num_iterations = -1; - - decoder->mImage->SetLoopCount(num_iterations); + PRInt32 num_plays = png_get_num_plays(png_ptr, info_ptr); + decoder->mImage->SetLoopCount(num_plays - 1); } if (!(decoder->apngFlags & FRAME_HIDDEN)) {