gif2webp: fix transcode of loop count=65535

with loop_compatibility disabled (the default), non-zero loop counts
will be incremented by 1 for browser rendering compatibility. the max,
65535, is a special case as the muxer will fail if it is exceeded; avoid
increasing the limit in this case. this isn't 100% correct, but should
be close enough given the high number of iterations.

BUG=webp:382,webp:512

Change-Id: Icde3e98a58e9ee89604a72fafda30ab71060dec5
(cherry picked from commit af0e4fbb06)
(cherry picked from commit 4b282e13ad)
This commit is contained in:
James Zern 2018-05-09 17:36:13 -07:00
parent dcf860bad1
commit 1f14632a18
4 changed files with 21 additions and 3 deletions

View File

@ -143,8 +143,18 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
if (!ok) return 0; // These are fatal failures, can't proceed. if (!ok) return 0; // These are fatal failures, can't proceed.
if (is_multi_frame_image) { // Checks relevant for multi-frame images only. if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
ok = CompareValues(img1->loop_count, img2->loop_count, int max_loop_count_workaround = 0;
"Loop count mismatch") && ok; // Transcodes to webp increase the gif loop count by 1 for compatibility.
// When the gif has the maximum value the webp value will be off by one.
if ((img1->format == ANIM_GIF && img1->loop_count == 65536 &&
img2->format == ANIM_WEBP && img2->loop_count == 65535) ||
(img1->format == ANIM_WEBP && img1->loop_count == 65535 &&
img2->format == ANIM_GIF && img2->loop_count == 65536)) {
max_loop_count_workaround = 1;
}
ok = (max_loop_count_workaround ||
CompareValues(img1->loop_count, img2->loop_count,
"Loop count mismatch")) && ok;
ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor, ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor,
premultiply) && ok; premultiply) && ok;
} }

View File

@ -275,6 +275,7 @@ static int ReadAnimatedWebP(const char filename[],
prev_frame_timestamp = timestamp; prev_frame_timestamp = timestamp;
} }
ok = dump_ok; ok = dump_ok;
if (ok) image->format = ANIM_WEBP;
End: End:
WebPAnimDecoderDelete(dec); WebPAnimDecoderDelete(dec);
@ -684,6 +685,7 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
} }
} }
} }
image->format = ANIM_GIF;
DGifCloseFile(gif, NULL); DGifCloseFile(gif, NULL);
return 1; return 1;
} }

View File

@ -22,6 +22,11 @@
extern "C" { extern "C" {
#endif #endif
typedef enum {
ANIM_GIF,
ANIM_WEBP
} AnimatedFileFormat;
typedef struct { typedef struct {
uint8_t* rgba; // Decoded and reconstructed full frame. uint8_t* rgba; // Decoded and reconstructed full frame.
int duration; // Frame duration in milliseconds. int duration; // Frame duration in milliseconds.
@ -29,6 +34,7 @@ typedef struct {
} DecodedFrame; } DecodedFrame;
typedef struct { typedef struct {
AnimatedFileFormat format;
uint32_t canvas_width; uint32_t canvas_width;
uint32_t canvas_height; uint32_t canvas_height;
uint32_t bgcolor; uint32_t bgcolor;

View File

@ -460,7 +460,7 @@ int main(int argc, const char *argv[]) {
stored_loop_count = 1; stored_loop_count = 1;
loop_count = 1; loop_count = 1;
} }
} else if (loop_count > 0) { } else if (loop_count > 0 && loop_count < 65535) {
// adapt GIF's semantic to WebP's (except in the infinite-loop case) // adapt GIF's semantic to WebP's (except in the infinite-loop case)
loop_count += 1; loop_count += 1;
} }