diff --git a/include/SDL3_image/SDL_image.h b/include/SDL3_image/SDL_image.h index 92f87159..dcc06ba2 100644 --- a/include/SDL3_image/SDL_image.h +++ b/include/SDL3_image/SDL_image.h @@ -2403,6 +2403,18 @@ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadGIFAnimation_IO(SDL_IOStream */ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadWEBPAnimation_IO(SDL_IOStream *src); +/** +* An enum representing the status of the encoder and decoder. +*/ +typedef enum IMG_AnimationDecoderStatus +{ + IMG_DECODER_STATUS_OK, /**< Decoded the frame successfully. */ + IMG_DECODER_STATUS_FAILED, /**< Decoding the frame failed. Call SDL_GetError for more information. */ + IMG_DECODER_STATUS_COMPLETE, /**< No more frames available. */ + + IMG_DECODER_STATUS_INVALID, /**< Invalid decoder status that does not represent any valid status. */ +} IMG_AnimationDecoderStatus; + /** * An object representing the encoder context. */ @@ -2688,6 +2700,19 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL IMG_GetAnimationDecoderProperties(I */ extern SDL_DECLSPEC bool SDLCALL IMG_GetAnimationDecoderFrame(IMG_AnimationDecoder *decoder, SDL_Surface **frame, Uint64 *duration); +/** +* Get the decoder status indicating the current state of the decoder. +* +* \param decoder the decoder to get the status of. +* \returns the status of the underlying decoder, or IMG_DECODER_STATUS_INVALID if the given +* decoder is invalid. +* +* \since This function is available since SDL_image 3.4.0. +* +* \sa IMG_GetAnimationDecoderFrame +*/ +extern SDL_DECLSPEC IMG_AnimationDecoderStatus SDLCALL IMG_GetAnimationDecoderStatus(IMG_AnimationDecoder *decoder); + /** * Reset an animation decoder. * diff --git a/src/IMG_anim_decoder.c b/src/IMG_anim_decoder.c index 5bb0242f..e4f1fb1c 100644 --- a/src/IMG_anim_decoder.c +++ b/src/IMG_anim_decoder.c @@ -193,14 +193,23 @@ bool IMG_GetAnimationDecoderFrame(IMG_AnimationDecoder *decoder, SDL_Surface **f if (!duration) { duration = &temp_duration; } - SDL_ClearError(); + // Reset the status before trying to get the next frame. + decoder->status = IMG_DECODER_STATUS_OK; bool result = decoder->GetNextFrame(decoder, frame, duration); if (temp_frame) { SDL_DestroySurface(temp_frame); } + if (!result) { + if (SDL_GetError()[0] == '\0') { + decoder->status = IMG_DECODER_STATUS_COMPLETE; + } else { + decoder->status = IMG_DECODER_STATUS_FAILED; + } + } + if (result) { decoder->accumulated_pts += *duration; } else { @@ -242,12 +251,22 @@ bool IMG_ResetAnimationDecoder(IMG_AnimationDecoder *decoder) Uint64 IMG_CalculateDuration(IMG_AnimationDecoder* decoder, int delay_num, int delay_den) { - if (delay_den < 1) + if (delay_den < 1) { delay_den = 100; + } return (Uint64)SDL_round(((double)delay_num / delay_den) * ((double)decoder->timebase_denominator / (double)decoder->timebase_numerator)); } +IMG_AnimationDecoderStatus IMG_GetAnimationDecoderStatus(IMG_AnimationDecoder* decoder) +{ + if (!decoder) { + return IMG_DECODER_STATUS_INVALID; + } + + return decoder->status; +} + IMG_Animation *IMG_DecodeAsAnimation(SDL_IOStream *src, const char *format, int maxFrames) { IMG_AnimationDecoder *decoder = IMG_CreateAnimationDecoder_IO(src, false, format); diff --git a/src/IMG_anim_decoder.h b/src/IMG_anim_decoder.h index aca81c33..94088a71 100644 --- a/src/IMG_anim_decoder.h +++ b/src/IMG_anim_decoder.h @@ -23,6 +23,7 @@ typedef struct IMG_AnimationDecoderContext IMG_AnimationDecoderContext; struct IMG_AnimationDecoder { + IMG_AnimationDecoderStatus status; SDL_PropertiesID props; SDL_IOStream *src; Sint64 start; diff --git a/src/IMG_anim_encoder.c b/src/IMG_anim_encoder.c index 4c38861f..eecacd26 100644 --- a/src/IMG_anim_encoder.c +++ b/src/IMG_anim_encoder.c @@ -171,11 +171,12 @@ bool IMG_AddAnimationEncoderFrame(IMG_AnimationEncoder *encoder, SDL_Surface *su if (!surface || surface->w <= 0 || surface->h <= 0) { return SDL_InvalidParamError("surface"); } - bool result = encoder->AddFrame(encoder, surface, duration); - encoder->accumulated_pts += duration; - encoder->last_delay = duration; + if (result) { + encoder->accumulated_pts += duration; + encoder->last_delay = duration; + } return result; } diff --git a/src/IMG_webp.c b/src/IMG_webp.c index 102fe5db..0bd172f5 100644 --- a/src/IMG_webp.c +++ b/src/IMG_webp.c @@ -448,8 +448,9 @@ static bool IMG_AnimationDecoderGetNextFrame_Internal(IMG_AnimationDecoder *deco int totalFrames = decoder->ctx->iter.num_frames; int availableFrames = totalFrames - (decoder->ctx->iter.frame_num - 1); - if (availableFrames < 1) + if (availableFrames < 1) { return false; + } SDL_Surface *canvas = decoder->ctx->canvas; uint32_t bgcolor = decoder->ctx->bgcolor; diff --git a/src/SDL_image.sym b/src/SDL_image.sym index b3084cce..eb570463 100644 --- a/src/SDL_image.sym +++ b/src/SDL_image.sym @@ -83,5 +83,6 @@ SDL3_image_0.0.0 { IMG_ResetAnimationDecoder; IMG_CloseAnimationDecoder; IMG_GetAnimationDecoderProperties; + IMG_GetAnimationDecoderStatus; local: *; };