diff options
author | Liav A <liavalb@gmail.com> | 2023-01-15 21:50:32 +0200 |
---|---|---|
committer | Jelle Raaijmakers <jelle@gmta.nl> | 2023-01-18 21:48:35 +0100 |
commit | 649f78d0a4475a640ad353e1e879a7bb27db222b (patch) | |
tree | 5ef6f843a86a8c9aad5d76d180dc8c5d87ee2065 /Userland/Services | |
parent | 9f2d4d3fd590177c3b6615c18ae5ec7febdb1522 (diff) | |
download | serenity-649f78d0a4475a640ad353e1e879a7bb27db222b.zip |
LibGfx+Ladybird+Userland: Don't sniff for TGA images with only raw bytes
Because TGA images don't have magic bytes as a signature to be detected,
instead assume a sequence of ReadonlyBytes is a possible TGA image only
if we are given a path so we could check the extension of the file and
see if it's a TGA image.
When we know the path of the file being loaded, we will try to first
check its extension, and only if there's no match to a known decoder,
based on simple extension lookup, then we would probe for other formats
as usual with the normal sniffing method.
Diffstat (limited to 'Userland/Services')
-rw-r--r-- | Userland/Services/ImageDecoder/ConnectionFromClient.cpp | 70 | ||||
-rw-r--r-- | Userland/Services/ImageDecoder/ConnectionFromClient.h | 1 | ||||
-rw-r--r-- | Userland/Services/ImageDecoder/ImageDecoderServer.ipc | 1 |
3 files changed, 54 insertions, 18 deletions
diff --git a/Userland/Services/ImageDecoder/ConnectionFromClient.cpp b/Userland/Services/ImageDecoder/ConnectionFromClient.cpp index e95f9ae066..9f0bee865b 100644 --- a/Userland/Services/ImageDecoder/ConnectionFromClient.cpp +++ b/Userland/Services/ImageDecoder/ConnectionFromClient.cpp @@ -22,40 +22,74 @@ void ConnectionFromClient::die() Core::EventLoop::current().quit(0); } -Messages::ImageDecoderServer::DecodeImageResponse ConnectionFromClient::decode_image(Core::AnonymousBuffer const& encoded_buffer) +static void decode_image_to_bitmaps_and_durations_with_decoder(Gfx::ImageDecoder const& decoder, Vector<Gfx::ShareableBitmap>& bitmaps, Vector<u32>& durations) { - if (!encoded_buffer.is_valid()) { - dbgln_if(IMAGE_DECODER_DEBUG, "Encoded data is invalid"); - return nullptr; + for (size_t i = 0; i < decoder.frame_count(); ++i) { + auto frame_or_error = decoder.frame(i); + if (frame_or_error.is_error()) { + bitmaps.append(Gfx::ShareableBitmap {}); + durations.append(0); + } else { + auto frame = frame_or_error.release_value(); + bitmaps.append(frame.image->to_shareable_bitmap()); + durations.append(frame.duration); + } } +} + +static void decode_image_to_details(Core::AnonymousBuffer const& encoded_buffer, Optional<StringView> known_path, bool& is_animated, u32& loop_count, Vector<Gfx::ShareableBitmap>& bitmaps, Vector<u32>& durations) +{ + VERIFY(bitmaps.size() == 0); + VERIFY(durations.size() == 0); + VERIFY(!is_animated); + VERIFY(loop_count == 0); - auto decoder = Gfx::ImageDecoder::try_create(ReadonlyBytes { encoded_buffer.data<u8>(), encoded_buffer.size() }); + RefPtr<Gfx::ImageDecoder> decoder; + if (known_path.has_value()) + decoder = Gfx::ImageDecoder::try_create_for_raw_bytes_with_known_path(known_path.value(), ReadonlyBytes { encoded_buffer.data<u8>(), encoded_buffer.size() }); + else + decoder = Gfx::ImageDecoder::try_create_for_raw_bytes(ReadonlyBytes { encoded_buffer.data<u8>(), encoded_buffer.size() }); if (!decoder) { dbgln_if(IMAGE_DECODER_DEBUG, "Could not find suitable image decoder plugin for data"); - return { false, 0, Vector<Gfx::ShareableBitmap> {}, Vector<u32> {} }; + return; } if (!decoder->frame_count()) { dbgln_if(IMAGE_DECODER_DEBUG, "Could not decode image from encoded data"); - return { false, 0, Vector<Gfx::ShareableBitmap> {}, Vector<u32> {} }; + return; } + decode_image_to_bitmaps_and_durations_with_decoder(*decoder, bitmaps, durations); +} +Messages::ImageDecoderServer::DecodeImageWithKnownPathResponse ConnectionFromClient::decode_image_with_known_path(DeprecatedString const& path, Core::AnonymousBuffer const& encoded_buffer) +{ + if (!encoded_buffer.is_valid()) { + dbgln_if(IMAGE_DECODER_DEBUG, "Encoded data is invalid"); + return nullptr; + } + + bool is_animated = false; + u32 loop_count = 0; Vector<Gfx::ShareableBitmap> bitmaps; Vector<u32> durations; - for (size_t i = 0; i < decoder->frame_count(); ++i) { - auto frame_or_error = decoder->frame(i); - if (frame_or_error.is_error()) { - bitmaps.append(Gfx::ShareableBitmap {}); - durations.append(0); - } else { - auto frame = frame_or_error.release_value(); - bitmaps.append(frame.image->to_shareable_bitmap()); - durations.append(frame.duration); - } + decode_image_to_details(encoded_buffer, path.substring_view(0), is_animated, loop_count, bitmaps, durations); + return { is_animated, loop_count, bitmaps, durations }; +} + +Messages::ImageDecoderServer::DecodeImageResponse ConnectionFromClient::decode_image(Core::AnonymousBuffer const& encoded_buffer) +{ + if (!encoded_buffer.is_valid()) { + dbgln_if(IMAGE_DECODER_DEBUG, "Encoded data is invalid"); + return nullptr; } - return { decoder->is_animated(), static_cast<u32>(decoder->loop_count()), bitmaps, durations }; + bool is_animated = false; + u32 loop_count = 0; + Vector<Gfx::ShareableBitmap> bitmaps; + Vector<u32> durations; + decode_image_to_details(encoded_buffer, {}, is_animated, loop_count, bitmaps, durations); + return { is_animated, loop_count, bitmaps, durations }; } } diff --git a/Userland/Services/ImageDecoder/ConnectionFromClient.h b/Userland/Services/ImageDecoder/ConnectionFromClient.h index 6b8a5e8086..f137af3dfe 100644 --- a/Userland/Services/ImageDecoder/ConnectionFromClient.h +++ b/Userland/Services/ImageDecoder/ConnectionFromClient.h @@ -27,6 +27,7 @@ private: explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>); virtual Messages::ImageDecoderServer::DecodeImageResponse decode_image(Core::AnonymousBuffer const&) override; + virtual Messages::ImageDecoderServer::DecodeImageWithKnownPathResponse decode_image_with_known_path(DeprecatedString const& path, Core::AnonymousBuffer const&) override; }; } diff --git a/Userland/Services/ImageDecoder/ImageDecoderServer.ipc b/Userland/Services/ImageDecoder/ImageDecoderServer.ipc index 5ca2e40ea0..9492f685a0 100644 --- a/Userland/Services/ImageDecoder/ImageDecoderServer.ipc +++ b/Userland/Services/ImageDecoder/ImageDecoderServer.ipc @@ -4,4 +4,5 @@ endpoint ImageDecoderServer { decode_image(Core::AnonymousBuffer data) => (bool is_animated, u32 loop_count, Vector<Gfx::ShareableBitmap> bitmaps, Vector<u32> durations) + decode_image_with_known_path(DeprecatedString path, Core::AnonymousBuffer data) => (bool is_animated, u32 loop_count, Vector<Gfx::ShareableBitmap> bitmaps, Vector<u32> durations) } |