diff --git a/giflib.cpp b/giflib.cpp index b10efda0..64504af9 100644 --- a/giflib.cpp +++ b/giflib.cpp @@ -1134,32 +1134,55 @@ int giflib_decoder_get_loop_count(const giflib_decoder d) { return loop_count; } - // Read extension blocks + // Read all blocks until we find NETSCAPE2.0 or hit end GifRecordType recordType; - if (DGifGetRecordType(gif, &recordType) == GIF_OK && - recordType == EXTENSION_RECORD_TYPE) { - - GifByteType* ExtData; - int ExtFunction; - - if (DGifGetExtension(gif, &ExtFunction, &ExtData) == GIF_OK && ExtData != NULL) { - // Look for NETSCAPE2.0 extension - if (ExtFunction == APPLICATION_EXT_FUNC_CODE && ExtData[0] >= 11 && - memcmp(ExtData + 1, "NETSCAPE2.0", 11) == 0) { - // Get the next block with loop count - if (DGifGetExtensionNext(gif, &ExtData) == GIF_OK && - ExtData != NULL && - ExtData[0] >= 3 && - ExtData[1] == 1) { - - loop_count = ExtData[2] | (ExtData[3] << 8); + while (DGifGetRecordType(gif, &recordType) == GIF_OK) { + switch (recordType) { + case EXTENSION_RECORD_TYPE: { + GifByteType* ExtData; + int ExtFunction; + + if (DGifGetExtension(gif, &ExtFunction, &ExtData) == GIF_OK && ExtData != NULL) { + // Look for NETSCAPE2.0 extension + if (ExtFunction == APPLICATION_EXT_FUNC_CODE && ExtData[0] >= 11 && + memcmp(ExtData + 1, "NETSCAPE2.0", 11) == 0) { + // Get the next block with loop count + if (DGifGetExtensionNext(gif, &ExtData) == GIF_OK && + ExtData != NULL && + ExtData[0] >= 3 && + ExtData[1] == 1) { + loop_count = ExtData[2] | (ExtData[3] << 8); + goto cleanup; // Found what we need + } + } + + // Skip any remaining extension blocks + while (ExtData != NULL) { + if (DGifGetExtensionNext(gif, &ExtData) != GIF_OK) { + goto cleanup; + } + } } + break; } + + case IMAGE_DESC_RECORD_TYPE: + // Skip image data + if (DGifGetImageDesc(gif) != GIF_OK) { + goto cleanup; + } + break; + + case TERMINATE_RECORD_TYPE: + goto cleanup; + + default: + break; } } +cleanup: DGifCloseFile(gif, &error); delete loopReader; - return loop_count; } diff --git a/testdata/dispose_bgnd.gif b/testdata/dispose_bgnd.gif new file mode 100644 index 00000000..d6850401 Binary files /dev/null and b/testdata/dispose_bgnd.gif differ diff --git a/testdata/duplicate_number_of_loops.gif b/testdata/duplicate_number_of_loops.gif new file mode 100644 index 00000000..ac315ee9 Binary files /dev/null and b/testdata/duplicate_number_of_loops.gif differ diff --git a/webp_test.go b/webp_test.go index 2240eb9f..55588f95 100644 --- a/webp_test.go +++ b/webp_test.go @@ -413,6 +413,26 @@ func testNewWebpEncoderWithAnimatedGIFSource(t *testing.T) { resizeMethod: ImageOpsResize, wantLoops: 1, }, + { + name: "Animated GIF with duplicate number of loop count, use the first loop count", + inputPath: "testdata/duplicate_number_of_loops.gif", + outputPath: "testdata/out/duplicate_number_of_loops.webp", + width: 200, + height: 200, + quality: 80, + resizeMethod: ImageOpsResize, + wantLoops: 2, + }, + { + name: "Animated GIF with multiple extension blocks", + inputPath: "testdata/dispose_bgnd.gif", + outputPath: "testdata/out/dispose_bgnd.webp", + width: 200, + height: 200, + quality: 80, + resizeMethod: ImageOpsResize, + wantLoops: 0, + }, } for _, tc := range testCases {