From b973d323ba3460f9a0a1aaa04186af896241ea73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Sat, 8 Jan 2022 05:32:42 +0100 Subject: [PATCH] Fix GIF decoding for certain files The handling is not perfect yet, but it should be fine enough. --- fiv-io.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/fiv-io.c b/fiv-io.c index d539f1a..236929a 100644 --- a/fiv-io.c +++ b/fiv-io.c @@ -564,10 +564,17 @@ load_wuffs_frame(struct load_wuffs_frame_context *ctx, GError **error) return false; } + // Wuffs' test/data/animated-red-blue.gif, e.g., needs this handling. + cairo_format_t decode_format = ctx->cairo_format; + if (wuffs_base__frame_config__index(&fc) > 0 && + wuffs_base__pixel_config__pixel_format(&ctx->cfg.pixcfg).repr == + WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL) + decode_format = CAIRO_FORMAT_ARGB32; + bool success = false; unsigned char *targetbuf = NULL; cairo_surface_t *surface = - cairo_image_surface_create(ctx->cairo_format, ctx->width, ctx->height); + cairo_image_surface_create(decode_format, ctx->width, ctx->height); cairo_status_t surface_status = cairo_surface_status(surface); if (surface_status != CAIRO_STATUS_SUCCESS) { set_error(error, cairo_status_to_string(surface_status)); @@ -659,6 +666,7 @@ load_wuffs_frame(struct load_wuffs_frame_context *ctx, GError **error) cairo_surface_mark_dirty(canvas); // Apply that frame's disposal method. + // XXX: We do not expect opaque pictures to receive holes this way. wuffs_base__rect_ie_u32 bounds = wuffs_base__frame_config__bounds(&ctx->last_fc); // TODO(p): This field needs to be colour-managed. @@ -686,6 +694,8 @@ load_wuffs_frame(struct load_wuffs_frame_context *ctx, GError **error) // TODO(p): Implement, it seems tricky. // Might need another surface to keep track of the state. break; + case WUFFS_BASE__ANIMATION_DISPOSAL__NONE: + break; } // Paint the current frame over that, within its bounds. @@ -844,8 +854,6 @@ open_wuffs(wuffs_base__image_decoder *dec, wuffs_base__io_buffer src, // Wuffs maps tRNS to BGRA in `decoder.decode_trns?`, we should be fine. // wuffs_base__pixel_format__transparency() doesn't reflect the image file. - // TODO(p): See if wuffs_base__image_config__first_frame_is_opaque() causes - // issues with animations, and eventually ensure an alpha-capable format. bool opaque = wuffs_base__image_config__first_frame_is_opaque(&ctx.cfg); // Wuffs' API is kind of awful--we want to catch wide RGB and wide grey. @@ -886,6 +894,8 @@ open_wuffs(wuffs_base__image_decoder *dec, wuffs_base__io_buffer src, ctx.cairo_format = CAIRO_FORMAT_RGB30; } else if (opaque) { // BGRX doesn't have as wide swizzler support, namely in GIF. + // Moreover, follower frames may still be partly transparent. + // Therefore, we choose to keep "wuffs_format" intact. ctx.cairo_format = CAIRO_FORMAT_RGB24; } else if (!ctx.target) { wuffs_format = WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL;