This adds support for animations with heterogeneous frame durations
without sacrificing CPU (bug#47895), and plugs a memory leak in and
speeds up WebP animations (bug#66221).
* lisp/image.el (image-animate): No need to stash
image-multi-frame-p data here, as image-animate-timeout now
refetches it for each animation frame.
(image-show-frame): Fetch image-multi-frame-p anew when checking
bounds; a cached value risks going stale. This is not on the hot
path for animations, and is mainly used when framewise stepping
through an animation interactively.
(image-animate-timeout): Fetch current frame duration anew but do so
before image-show-frame to ensure an image cache hit (bug#47895,
bug#66221). Include time taken by local arithmetic in
'time-to-load-image'. Update commentary.
* src/image.c (parse_image_spec): Simplify using FIXNATP.
(filter_image_spec): Remove check for :animate-multi-frame-data as
it is no longer used by image.el.
[HAVE_ANIMATION && HAVE_GIF] (struct gif_anim_handle):
[HAVE_ANIMATION && HAVE_WEBP] (struct webp_anim_handle): New
structures formalizing animation cache handles, and allowing for
more than two custom fields per image type.
(struct anim_cache): Replace generic handle and temp pointers with a
union of gif_anim_handle and webp_anim_handle. All uses updated.
Update destructor signature accordingly.
(anim_create_cache): Use xzalloc to zero-initialize both integer and
pointer fields. Initialize frames, width, height to -1 for
consistency with index. Mark as ATTRIBUTE_MALLOC.
(anim_prune_animation_cache): Check whether destructor (not handle)
is null before calling it.
(gif_clear_image): Note in commentary that WebP also uses it.
(gif_destroy): Free pixmap here now that prune_anim_cache no longer
does it automatically. Remove unused gif_err variable.
(gif_load): Avoid UB from casting destructor to a different type.
Don't redundantly check for null before xfree. Change default frame
delay from 15fps to t, which image-multi-frame-p will translate into
image-default-frame-delay, which the user can control.
[HAVE_WEBP && WINDOWSNT] (init_webp_functions): Reconcile library
definitions with current webp_load implementation.
(webp_destroy): Free owned copy of input WebP bitstream contents.
(webp_load): Ownership of both input and decoded memory is a
function of :data vs :file and animated vs still. Make this and
transfers of ownership to animation cache clearer by using distinct
copy/view variables. Also make resource freeing clearer by using a
single unconditional cleanup and exit path. Check animation cache
early to avoid rereading bitstream and reparsing headers on each
call. Remove redundant call to WebPGetInfo since WebPGetFeatures
does the same thing. Check more libwebpdemux return values for
failure and fix file name reported in error messages. Remove unset
local variable 'file'. If requested :index is ahead, fast-forward
instead of restarting from first frame. If requested :index is
behind, reset animation decoder to first frame instead of deleting
and recreating it. Reuse animation decoder's own WebPAnimInfo and
WebPDemuxer instance instead of creating and deleting a separate
WebPDemuxer. Fix leak when copying :data to animation cache. Fix
frame duration calculation, and return each frame's own duration now
that image.el supports it. Return t as a default frame duration, as
per gif_load. Consistently use WebPBitstreamFeatures to simplify
control flow. Don't pollute lisp_data image-metadata for still
images with animation-related properties.
(image_types) [HAVE_WEBP]: Use gif_clear_image to clear lisp_data
for consistency with GIF code.
(syms_of_image): Remove QCanimate_multi_frame_data; no longer used.
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Copyright (C) 2001-2026 Free Software Foundation, Inc.
See the end of the file for license conditions.
This directory contains the source files for the C component of GNU Emacs.
Nothing in this directory is needed for using Emacs once it is built
and installed, if the dumped Emacs is copied elsewhere.
See the files ../README and then ../INSTALL for installation instructions.
The file 'Makefile.in' is used as a template by the script
'../configure' to produce 'Makefile'. This is the file which actually
controls the compilation of Emacs C source files. All of this should
work transparently; you should only need to change to the parent
directory, run './configure', and then run 'make'.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.