From c77620931df21c58a0a85471403fba488c693d5c Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Wed, 10 Jun 2026 13:02:40 +0100 Subject: [PATCH] ImageDecoder: Truncate animated decodes at the first failed frame This matches the behavior of other engines --- .../ImageDecoder/ConnectionFromClient.cpp | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Services/ImageDecoder/ConnectionFromClient.cpp b/Services/ImageDecoder/ConnectionFromClient.cpp index b10eaa3a12..88ef24606f 100644 --- a/Services/ImageDecoder/ConnectionFromClient.cpp +++ b/Services/ImageDecoder/ConnectionFromClient.cpp @@ -152,16 +152,14 @@ static ErrorOr decode_image_to_details(Core: bitmaps.ensure_capacity(batch_size); for (u32 i = 0; i < batch_size; ++i) { auto frame_or_error = decoder->frame(i, ideal_size); - if (frame_or_error.is_error()) { - bitmaps.unchecked_append({}); - } else { - auto frame = frame_or_error.release_value(); - frame.image->set_alpha_type_destructive(Gfx::AlphaType::Premultiplied); - bitmaps.unchecked_append(frame.image); - // If frame_duration() returned 0, use the actual decoded duration. - if (result.durations[i] == 0) - result.durations[i] = frame.duration; - } + if (frame_or_error.is_error()) + break; + auto frame = frame_or_error.release_value(); + frame.image->set_alpha_type_destructive(Gfx::AlphaType::Premultiplied); + bitmaps.unchecked_append(frame.image); + // If frame_duration() returned 0, use the actual decoded duration. + if (result.durations[i] == 0) + result.durations[i] = frame.duration; } // Keep decoder alive for future frame requests. @@ -289,7 +287,13 @@ NonnullRefPtr ConnectionFromClient::start_fram if (job->is_canceled()) return FrameDecodeResult {}; - auto frame = TRY(session->decoder->frame(i)); + auto frame_or_error = session->decoder->frame(i); + if (frame_or_error.is_error()) { + if (frames.is_empty()) + return frame_or_error.release_error(); + break; + } + auto frame = frame_or_error.release_value(); frame.image->set_alpha_type_destructive(Gfx::AlphaType::Premultiplied); frames.unchecked_append(move(frame)); }