Commit 5c38bb6f2 for imagemagick.org
commit 5c38bb6f21806ccd8c0f9e3662a4267c7da45c5b
Author: Madars <mad182@gmail.com>
Date: Tue Mar 24 13:53:40 2026 +0200
Skip frame duplication for APNG in video coder (#8636)
The video coder duplicates frames to simulate timing at a fixed
framerate for video formats. APNG supports per-frame delays natively
via fcTL chunks, so this duplication is unnecessary and causes the
output to have double (or more) the expected number of frames.
diff --git a/coders/video.c b/coders/video.c
index a48c9c458..ec18493c7 100644
--- a/coders/video.c
+++ b/coders/video.c
@@ -578,7 +578,8 @@ static MagickBooleanType WriteVIDEOImage(const ImageInfo *image_info,
scene;
ssize_t
- i;
+ i,
+ length_of_delay_loop;
unsigned char
*blob;
@@ -620,7 +621,11 @@ static MagickBooleanType WriteVIDEOImage(const ImageInfo *image_info,
length=0;
scene=p->scene;
delay=100.0*p->delay/MagickMax(1.0*p->ticks_per_second,1.0);
- for (i=0; i < (ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0); i++)
+ if (LocaleNCompare(image_info->magick,"APNG",MagickPathExtent) == 0)
+ length_of_delay_loop=1;
+ else
+ length_of_delay_loop=(ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0);
+ for (i=0; i < length_of_delay_loop; i++)
{
p->scene=count;
count++;
@@ -735,7 +740,11 @@ static MagickBooleanType WriteVIDEOImage(const ImageInfo *image_info,
for (p=clone_images; p != (Image *) NULL; p=GetNextImageInList(p))
{
delay=100.0*p->delay/MagickMax(1.0*p->ticks_per_second,1.0);
- for (i=0; i < (ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0); i++)
+ if (LocaleNCompare(image_info->magick,"APNG",MagickPathExtent) == 0)
+ length_of_delay_loop=1;
+ else
+ length_of_delay_loop=(ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0);
+ for (i=0; i < length_of_delay_loop; i++)
{
(void) FormatLocaleString(p->filename,MagickPathExtent,"%s%.20g.%s",
basename,(double) count++,intermediate_format);