Commit 2b39b7598 for imagemagick.org

commit 2b39b75987d293616408c6ee3aed8b1f66ebd172
Author: Madars <mad182@gmail.com>
Date:   Sat Mar 21 14:27:07 2026 +0200

    Fix animated JXL frame delay handling (#8622)

    Read per-frame duration from JxlFrameHeader during decode by calling
    JxlDecoderGetFrameHeader() in the JXL_DEC_FRAME handler, setting
    image->delay from frame_header.duration.

    Write per-frame delay from image->delay during encode instead of
    hardcoding frame_header.duration to 1. This preserves the original
    animation timing when resizing or editing animated JXL files.

diff --git a/coders/jxl.c b/coders/jxl.c
index a1518d970..971b4b6d0 100644
--- a/coders/jxl.c
+++ b/coders/jxl.c
@@ -626,6 +626,9 @@ static Image *ReadJXLImage(const ImageInfo *image_info,
       }
       case JXL_DEC_FRAME:
       {
+        JxlFrameHeader
+          frame_header;
+
         if (image_count++ != 0)
           {
             JXLAddProfilesToImage(image,&exif_profile,&xmp_profile,exception);
@@ -638,6 +641,9 @@ static Image *ReadJXLImage(const ImageInfo *image_info,
             image=SyncNextImageInList(image);
             JXLInitImage(image,&basic_info);
           }
+        (void) memset(&frame_header,0,sizeof(frame_header));
+        if (JxlDecoderGetFrameHeader(jxl_info,&frame_header) == JXL_DEC_SUCCESS)
+          image->delay=(size_t) frame_header.duration;
         break;
       }
       case JXL_DEC_NEED_IMAGE_OUT_BUFFER:
@@ -1070,7 +1076,6 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image,
       basic_info.animation.tps_numerator=(uint32_t) image->ticks_per_second;
       basic_info.animation.tps_denominator=1;
       JxlEncoderInitFrameHeader(&frame_header);
-      frame_header.duration=1;
     }
   jxl_status=JxlEncoderSetBasicInfo(jxl_info,&basic_info);
   if (jxl_status != JXL_ENC_SUCCESS)
@@ -1177,6 +1182,7 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image,

     if (basic_info.have_animation == JXL_TRUE)
       {
+        frame_header.duration=(uint32_t) image->delay;
         jxl_status=JxlEncoderSetFrameHeader(frame_settings,&frame_header);
         if (jxl_status != JXL_ENC_SUCCESS)
           break;