gif2webp: handle 1-frame case properly + fix anim_diff

follow-up to commit b4e046778

Change-Id: I3c7617d09682262ca7929e6a3e56777b163cce45
This commit is contained in:
Pascal Massimino 2017-09-20 14:08:31 -07:00
parent c7f295d30c
commit 3c74c645ca
2 changed files with 22 additions and 10 deletions

View File

@ -425,6 +425,11 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
} }
// Find appropriate app extension and get loop count from the next extension. // 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) { static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
int i; int i;
for (i = 0; i < gif->ImageCount; ++i) { for (i = 0; i < gif->ImageCount; ++i) {
@ -442,12 +447,13 @@ static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
if (signature_is_ok && if (signature_is_ok &&
eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 && eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 &&
eb2->Bytes[0] == 1) { eb2->Bytes[0] == 1) {
return ((uint32_t)(eb2->Bytes[2]) << 8) + const uint32_t extra_loop = ((uint32_t)(eb2->Bytes[2]) << 8) +
((uint32_t)(eb2->Bytes[1]) << 0); ((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. // Get duration of 'n'th frame in milliseconds.

View File

@ -106,7 +106,7 @@ int main(int argc, const char *argv[]) {
WebPAnimEncoderOptions enc_options; WebPAnimEncoderOptions enc_options;
WebPConfig config; 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 done;
int c; int c;
int quiet = 0; int quiet = 0;
@ -282,7 +282,7 @@ int main(int argc, const char *argv[]) {
if (!DGifGetImageDesc(gif)) goto End; if (!DGifGetImageDesc(gif)) goto End;
if (is_first_frame) { if (frame_number == 0) {
if (verbose) { if (verbose) {
printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight); 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"); "a memory error.\n");
goto End; goto End;
} }
is_first_frame = 0;
} }
// Some even more broken GIF can have sub-rect with zero width/height. // 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); GIFBlendFrames(&frame, &gif_rect, &curr_canvas);
if (!WebPAnimEncoderAdd(enc, &curr_canvas, frame_timestamp, &config)) { 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. // Update canvases.
@ -451,9 +454,12 @@ int main(int argc, const char *argv[]) {
if (!loop_compatibility) { if (!loop_compatibility) {
if (!stored_loop_count) { if (!stored_loop_count) {
// if no loop-count element is seen, the default is '1' (loop-once) // if no loop-count element is seen, the default is '1' (loop-once)
// and we need to signal it explicitly in WebP. // and we need to signal it explicitly in WebP. Note however that
stored_loop_count = 1; // in case there's a single frame, we still don't need to store it.
loop_count = 1; if (frame_number > 1) {
stored_loop_count = 1;
loop_count = 1;
}
} else if (loop_count > 0) { } else if (loop_count > 0) {
// 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;