From 3c74c645ca241f9e481ab441cedaf28cebaf7716 Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Wed, 20 Sep 2017 14:08:31 -0700 Subject: [PATCH] gif2webp: handle 1-frame case properly + fix anim_diff follow-up to commit b4e046778 Change-Id: I3c7617d09682262ca7929e6a3e56777b163cce45 --- examples/anim_util.c | 12 +++++++++--- examples/gif2webp.c | 20 +++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/examples/anim_util.c b/examples/anim_util.c index c95deb16..d1a48887 100644 --- a/examples/anim_util.c +++ b/examples/anim_util.c @@ -425,6 +425,11 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) { } // Find appropriate app extension and get loop count from the next extension. +// We use Chrome's interpretation of the 'loop_count' semantics: +// if not present -> loop once +// if present and loop_count == 0, return 0 ('infinite'). +// if present and loop_count != 0, it's the number of *extra* loops +// so we need to return loop_count + 1 as total loop number. static uint32_t GetLoopCountGIF(const GifFileType* const gif) { int i; for (i = 0; i < gif->ImageCount; ++i) { @@ -442,12 +447,13 @@ static uint32_t GetLoopCountGIF(const GifFileType* const gif) { if (signature_is_ok && eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 && eb2->Bytes[0] == 1) { - return ((uint32_t)(eb2->Bytes[2]) << 8) + - ((uint32_t)(eb2->Bytes[1]) << 0); + const uint32_t extra_loop = ((uint32_t)(eb2->Bytes[2]) << 8) + + ((uint32_t)(eb2->Bytes[1]) << 0); + return (extra_loop > 0) ? extra_loop + 1 : 0; } } } - return 0; // Default. + return 1; // Default. } // Get duration of 'n'th frame in milliseconds. diff --git a/examples/gif2webp.c b/examples/gif2webp.c index 7287bea8..0a7c7a88 100644 --- a/examples/gif2webp.c +++ b/examples/gif2webp.c @@ -106,7 +106,7 @@ int main(int argc, const char *argv[]) { WebPAnimEncoderOptions enc_options; WebPConfig config; - int is_first_frame = 1; // Whether we are processing the first frame. + int frame_number = 0; // Whether we are processing the first frame. int done; int c; int quiet = 0; @@ -282,7 +282,7 @@ int main(int argc, const char *argv[]) { if (!DGifGetImageDesc(gif)) goto End; - if (is_first_frame) { + if (frame_number == 0) { if (verbose) { printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight); } @@ -324,7 +324,6 @@ int main(int argc, const char *argv[]) { "a memory error.\n"); goto End; } - is_first_frame = 0; } // Some even more broken GIF can have sub-rect with zero width/height. @@ -341,7 +340,11 @@ int main(int argc, const char *argv[]) { GIFBlendFrames(&frame, &gif_rect, &curr_canvas); if (!WebPAnimEncoderAdd(enc, &curr_canvas, frame_timestamp, &config)) { - fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc)); + fprintf(stderr, "Error while adding frame #%d: %s\n", frame_number, + WebPAnimEncoderGetError(enc)); + goto End; + } else { + ++frame_number; } // Update canvases. @@ -451,9 +454,12 @@ int main(int argc, const char *argv[]) { if (!loop_compatibility) { if (!stored_loop_count) { // if no loop-count element is seen, the default is '1' (loop-once) - // and we need to signal it explicitly in WebP. - stored_loop_count = 1; - loop_count = 1; + // and we need to signal it explicitly in WebP. Note however that + // in case there's a single frame, we still don't need to store it. + if (frame_number > 1) { + stored_loop_count = 1; + loop_count = 1; + } } else if (loop_count > 0) { // adapt GIF's semantic to WebP's (except in the infinite-loop case) loop_count += 1;