r/FlutterDev • u/Sure_Education_828 • 2h ago
Discussion Animated GIFs/WebPs ignore cacheWidth in Flutter. Here’s why, and an engine PR to fix it
If you display animated GIFs or WebPs with cacheWidth, cacheHeight or ResizeImage, the resize is silently ignored: every frame is still decoded and uploaded at full size. A 1000×1000 GIF shown at 200×200 costs about 4 MB per uploaded frame; with the resize honored it would be about 160 KB. This is #90804 (open since 2021), and #137668 for animated WebP.
Why it happens
In the engine, ImageDescriptor::instantiateCodec passes the target size only to the single-frame codec. Images with more than one frame go to MultiFrameCodec, which never receives it.
Why it’s not a one-line fix
Animated frames aren’t independent images. Most frames are drawn on top of earlier ones, each with its own rect, blending and disposal (keep, clear to background, restore previous), all in full-canvas coordinates. Skia can decode GIF/WebP frames directly at a smaller size, but an emulation of the engine’s frame logic on top of Skia’s real decoders showed that doing so with the engine’s single cached frame gives wrong pixels at frame edges in some files (1px transparent slivers).
The fix
Composite at full size exactly as today, then resize only the finished frame, with the same bilinear filter Flutter already uses for still images, before uploading it. Every frame you get is today’s frame, downscaled. It applies to GIF, animated WebP and APNG on the native backends (Skia and Impeller), with no API changes: cacheWidth and ResizeImage simply start working. The CPU buffer used for compositing stays full size, as today.
Status
PR: https://github.com/flutter/flutter/pull/194615. It’s waiting for review, and CI hasn’t run yet. Web (CanvasKit/Skwasm) isn’t covered.
Until it lands
Resize animated images before they reach the app, on your server or by converting them to animated WebP or video at the size you display.
Feedback on the approach or the C++ is very welcome. If this affects your app, a 👍 on #90804 is more helpful than “+1” comments on the PR.