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);