SDL_image: Added constants for format-specific properties

From a6f4d44411018eb701b3a6f4ac3070b8fca09d50 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 31 Dec 2025 19:56:22 -0800
Subject: [PATCH] Added constants for format-specific properties

Fixes https://github.com/libsdl-org/SDL_image/issues/646
---
 include/SDL3_image/SDL_image.h | 10 ++++++++++
 src/IMG_avif.c                 | 10 +++++-----
 src/IMG_gif.c                  |  6 +++---
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/include/SDL3_image/SDL_image.h b/include/SDL3_image/SDL_image.h
index 9f45cd38..f7d51fd5 100644
--- a/include/SDL3_image/SDL_image.h
+++ b/include/SDL3_image/SDL_image.h
@@ -2898,6 +2898,10 @@ extern SDL_DECLSPEC IMG_AnimationEncoder * SDLCALL IMG_CreateAnimationEncoderWit
 #define IMG_PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_NUMERATOR_NUMBER      "SDL_image.animation_encoder.create.timebase.numerator"
 #define IMG_PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER    "SDL_image.animation_encoder.create.timebase.denominator"
 
+#define IMG_PROP_ANIMATION_ENCODER_CREATE_AVIF_MAX_THREADS_NUMBER        "SDL_image.animation_encoder.create.avif.max_threads"
+#define IMG_PROP_ANIMATION_ENCODER_CREATE_AVIF_KEYFRAME_INTERVAL_NUMBER  "SDL_image.animation_encoder.create.avif.keyframe_interval"
+#define IMG_PROP_ANIMATION_ENCODER_CREATE_GIF_USE_LUT_BOOLEAN            "SDL_image.animation_encoder.create.gif.use_lut"
+
 /**
  * Add a frame to an animation encoder.
  *
@@ -3063,6 +3067,12 @@ extern SDL_DECLSPEC IMG_AnimationDecoder * SDLCALL IMG_CreateAnimationDecoderWit
 #define IMG_PROP_ANIMATION_DECODER_CREATE_TIMEBASE_NUMERATOR_NUMBER      "SDL_image.animation_decoder.create.timebase.numerator"
 #define IMG_PROP_ANIMATION_DECODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER    "SDL_image.animation_decoder.create.timebase.denominator"
 
+#define IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_MAX_THREADS_NUMBER        "SDL_image.animation_decoder.create.avif.max_threads"
+#define IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_INCREMENTAL_BOOLEAN "SDL_image.animation_decoder.create.avif.allow_incremental"
+#define IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_PROGRESSIVE_BOOLEAN "SDL_image.animation_decoder.create.avif.allow_progressive"
+#define IMG_PROP_ANIMATION_DECODER_CREATE_GIF_TRANSPARENT_COLOR_INDEX_NUMBER "SDL_image.animation_encoder.create.gif.transparent_color_index"
+#define IMG_PROP_ANIMATION_DECODER_CREATE_GIF_NUM_COLORS_NUMBER          "SDL_image.animation_encoder.create.gif.num_colors"
+
 /**
  * Get the properties of an animation decoder.
  *
diff --git a/src/IMG_avif.c b/src/IMG_avif.c
index 1704f373..2da1b8b1 100644
--- a/src/IMG_avif.c
+++ b/src/IMG_avif.c
@@ -1100,14 +1100,14 @@ bool IMG_CreateAVIFAnimationDecoder(IMG_AnimationDecoder *decoder, SDL_Propertie
     ctx->current_frame = 0;
 
     int maxLCores = SDL_GetNumLogicalCPUCores();
-    int maxThreads = (int)SDL_GetNumberProperty(props, "avif.maxthreads", maxLCores / 2);
+    int maxThreads = (int)SDL_GetNumberProperty(props, IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_MAX_THREADS_NUMBER, maxLCores / 2);
     maxThreads = SDL_clamp(maxThreads, 1, maxLCores);
     ctx->decoder->maxThreads = maxThreads;
 
-    bool allowProgressive = SDL_GetBooleanProperty(props, "avif.allowprogressive", true);
+    bool allowProgressive = SDL_GetBooleanProperty(props, IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_PROGRESSIVE_BOOLEAN, true);
     ctx->decoder->allowProgressive = allowProgressive ? AVIF_TRUE : AVIF_FALSE;
 
-    bool allowIncremental = SDL_GetBooleanProperty(props, "avif.allowincremental", false);
+    bool allowIncremental = SDL_GetBooleanProperty(props, IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_PROGRESSIVE_BOOLEAN, false);
     ctx->decoder->allowIncremental = allowIncremental ? AVIF_TRUE : AVIF_FALSE;
 
     bool ignoreProps = SDL_GetBooleanProperty(props, IMG_PROP_METADATA_IGNORE_PROPS_BOOLEAN, false);
@@ -1574,10 +1574,10 @@ bool IMG_CreateAVIFAnimationEncoder(IMG_AnimationEncoder *encoder, SDL_Propertie
     }
 
     int availableLCores = SDL_GetNumLogicalCPUCores();
-    int threads = (int)SDL_GetNumberProperty(props, "maxthreads", availableLCores / 2);
+    int threads = (int)SDL_GetNumberProperty(props, IMG_PROP_ANIMATION_ENCODER_CREATE_AVIF_MAX_THREADS_NUMBER, availableLCores / 2);
     threads = SDL_clamp(threads, 1, availableLCores);
 
-    int keyFrameInterval = (int)SDL_GetNumberProperty(props, "keyframeinterval", 0);
+    int keyFrameInterval = (int)SDL_GetNumberProperty(props, IMG_PROP_ANIMATION_ENCODER_CREATE_AVIF_KEYFRAME_INTERVAL_NUMBER, 0);
 
     ctx->encoder->maxThreads = threads;
     ctx->encoder->quality = encoder->quality;
diff --git a/src/IMG_gif.c b/src/IMG_gif.c
index be29686f..7cb4a23a 100644
--- a/src/IMG_gif.c
+++ b/src/IMG_gif.c
@@ -2765,8 +2765,8 @@ bool IMG_CreateGIFAnimationEncoder(IMG_AnimationEncoder *encoder, SDL_Properties
     int transparent_index = -1;
     uint16_t num_global_colors = 256;
 
-    transparent_index = (int)SDL_GetNumberProperty(props, "transparent_color_index", -1);
-    Sint64 globalcolors = SDL_GetNumberProperty(props, "num_colors", 256);
+    transparent_index = (int)SDL_GetNumberProperty(props, IMG_PROP_ANIMATION_DECODER_CREATE_GIF_TRANSPARENT_COLOR_INDEX_NUMBER, -1);
+    Sint64 globalcolors = SDL_GetNumberProperty(props, IMG_PROP_ANIMATION_DECODER_CREATE_GIF_NUM_COLORS_NUMBER, 256);
     if (globalcolors <= 1 || (globalcolors & (globalcolors - 1)) != 0 || globalcolors > 256) {
         return SDL_SetError("GIF stream property 'num_colors' must be a power of 2 (starting from 2, up to 256).");
     }
@@ -2810,7 +2810,7 @@ bool IMG_CreateGIFAnimationEncoder(IMG_AnimationEncoder *encoder, SDL_Properties
     ctx->numGlobalColors = num_global_colors;
     ctx->transparentColorIndex = transparent_index;
     ctx->firstFrame = true;
-    ctx->use_lut = SDL_GetBooleanProperty(props, "use_lut", false);
+    ctx->use_lut = SDL_GetBooleanProperty(props, IMG_PROP_ANIMATION_ENCODER_CREATE_GIF_USE_LUT_BOOLEAN, false);
 
     encoder->ctx = ctx;
     encoder->AddFrame = AnimationEncoder_AddFrame;