Commit f1d8c9032 for imagemagick.org
commit f1d8c903247ede3e99b231d6c0c387066d311435
Author: Dirk Lemstra <dirk@lemstra.org>
Date: Sun Oct 11 20:27:20 2026 +0200
Select image-sequence tracks when reading HEIC animations
diff --git a/coders/heic.c b/coders/heic.c
index 80376c9c6..2eeac6b9c 100644
--- a/coders/heic.c
+++ b/coders/heic.c
@@ -698,8 +698,59 @@ static MagickBooleanType ReadHEICImageHandle(const ImageInfo *image_info,
}
#if LIBHEIF_NUMERIC_VERSION >= HEIC_COMPUTE_NUMERIC_VERSION(1,20,0)
+static MagickBooleanType GetHEICSequenceTrack(Image *image,
+ struct heif_context *heif_context,heif_track **sequence_track,
+ ExceptionInfo *exception)
+{
+ int
+ i,
+ number_tracks;
+
+ uint32_t
+ *track_ids;
+
+ *sequence_track=(heif_track *) NULL;
+ number_tracks=heif_context_number_of_sequence_tracks(heif_context);
+ if (AcquireMagickResource(ListLengthResource,(MagickSizeType) number_tracks) == MagickFalse)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitError,"ListLengthExceedsLimit","`%s'",image->filename);
+ return(MagickFalse);
+ }
+ track_ids=(uint32_t *) AcquireQuantumMemory((size_t) number_tracks,sizeof(*track_ids));
+ if (track_ids == (uint32_t *) NULL)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+ return(MagickFalse);
+ }
+ heif_context_get_track_ids(heif_context,track_ids);
+ for (i=0; i < number_tracks; i++)
+ {
+ heif_track
+ *track;
+
+ track=heif_context_get_track(heif_context,track_ids[i]);
+ if (track == (heif_track *) NULL)
+ {
+ track_ids=(uint32_t *) RelinquishMagickMemory(track_ids);
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ CorruptImageError,"ImageTypeNotSupported","`%s'",image->filename);
+ return(MagickFalse);
+ }
+ if (heif_track_get_track_handler_type(track) == heif_track_type_image_sequence)
+ {
+ *sequence_track=track;
+ break;
+ }
+ heif_track_release(track);
+ }
+ track_ids=(uint32_t *) RelinquishMagickMemory(track_ids);
+ return(MagickTrue);
+}
+
static MagickBooleanType ReadHEICSequenceFrames(const ImageInfo *image_info,
- Image *image,struct heif_context *heif_context,ExceptionInfo *exception)
+ Image *image,heif_track *track,ExceptionInfo *exception)
{
const uint8_t
*pixels[4];
@@ -708,9 +759,6 @@ static MagickBooleanType ReadHEICSequenceFrames(const ImageInfo *image_info,
channels[4] = { heif_channel_R, heif_channel_G, heif_channel_B,
heif_channel_Alpha };
- heif_track
- *track;
-
int
bits_per_pixel[4],
has_alpha = 0,
@@ -740,13 +788,6 @@ static MagickBooleanType ReadHEICSequenceFrames(const ImageInfo *image_info,
uint32_t
timescale;
- /*
- Get the first visual track from the sequence.
- */
- track=heif_context_get_track(heif_context,0);
- if (track == (heif_track *) NULL)
- return(MagickFalse);
-
error=heif_track_get_image_resolution(track,&track_width,&track_height);
if (error.code != heif_error_Ok)
{
@@ -1111,11 +1152,22 @@ static Image *ReadHEICImage(const ImageInfo *image_info,ExceptionInfo *exception
(heif_read_main_brand(magic,sizeof(magic)) != heif_brand2_avif) &&
(heif_context_has_sequence(heif_context) != 0))
{
- status=ReadHEICSequenceFrames(image_info,image,heif_context,exception);
- heif_context_free(heif_context);
- if (status == MagickFalse)
- return(DestroyImageList(image));
- return(GetFirstImageInList(image));
+ heif_track
+ *track;
+
+ if (GetHEICSequenceTrack(image,heif_context,&track,exception) == MagickFalse)
+ {
+ heif_context_free(heif_context);
+ return(DestroyImageList(image));
+ }
+ if (track != (heif_track *) NULL)
+ {
+ status=ReadHEICSequenceFrames(image_info,image,track,exception);
+ heif_context_free(heif_context);
+ if (status == MagickFalse)
+ return(DestroyImageList(image));
+ return(GetFirstImageInList(image));
+ }
}
#endif
error=heif_context_get_primary_image_ID(heif_context,&primary_image_id);