diff options
author | Liav A <liavalb@gmail.com> | 2023-01-20 03:27:10 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-01-20 15:13:31 +0000 |
commit | 6e6999ce5767121a6904b6c36454723e39b9bf24 (patch) | |
tree | a13426f1402eaa030397c3545b694ae3683f6f2d /Userland/Libraries | |
parent | fedd18eb89db0f9a6b8047cd2a5a7d716cca9544 (diff) | |
download | serenity-6e6999ce5767121a6904b6c36454723e39b9bf24.zip |
LibGfx: Re-work the abstractions of sending image for decoding over IPC
Originally I simply thought that passing file paths is quite OK, but as
Linus pointed to, it turned out that passing file paths to ensure some
files are able to be decoded is awkward because it does not work with
images being served over HTTP.
Therefore, ideally we should just use the MIME type as an optional
argument to ensure that we can always fallback to use that in case
sniffing for the correct image type has failed so we can still detect
files like with the TGA format, which has no magic bytes.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibGUI/ImageWidget.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Bitmap.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/ImageDecoder.cpp | 28 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/ImageDecoder.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibImageDecoderClient/Client.cpp | 41 | ||||
-rw-r--r-- | Userland/Libraries/LibImageDecoderClient/Client.h | 3 |
6 files changed, 23 insertions, 60 deletions
diff --git a/Userland/Libraries/LibGUI/ImageWidget.cpp b/Userland/Libraries/LibGUI/ImageWidget.cpp index 2800fe4f75..3de928bc46 100644 --- a/Userland/Libraries/LibGUI/ImageWidget.cpp +++ b/Userland/Libraries/LibGUI/ImageWidget.cpp @@ -6,6 +6,7 @@ */ #include <LibCore/MappedFile.h> +#include <LibCore/MimeData.h> #include <LibGUI/ImageWidget.h> #include <LibGUI/Painter.h> #include <LibGfx/Bitmap.h> @@ -76,7 +77,8 @@ void ImageWidget::load_from_file(StringView path) return; auto& mapped_file = *file_or_error.value(); - m_image_decoder = Gfx::ImageDecoder::try_create_for_raw_bytes_with_known_path(path, mapped_file.bytes()); + auto mime_type = Core::guess_mime_type_based_on_filename(path); + m_image_decoder = Gfx::ImageDecoder::try_create_for_raw_bytes(mapped_file.bytes(), mime_type); VERIFY(m_image_decoder); auto frame = m_image_decoder->frame(0).release_value_but_fixme_should_propagate_errors(); diff --git a/Userland/Libraries/LibGfx/Bitmap.cpp b/Userland/Libraries/LibGfx/Bitmap.cpp index 30073c6ae0..e46161f321 100644 --- a/Userland/Libraries/LibGfx/Bitmap.cpp +++ b/Userland/Libraries/LibGfx/Bitmap.cpp @@ -16,6 +16,7 @@ #include <AK/ScopeGuard.h> #include <AK/Try.h> #include <LibCore/MappedFile.h> +#include <LibCore/MimeData.h> #include <LibCore/System.h> #include <LibGfx/Bitmap.h> #include <LibGfx/ImageDecoder.h> @@ -143,7 +144,8 @@ ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::try_load_from_file(StringView path, int s ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::try_load_from_fd_and_close(int fd, StringView path) { auto file = TRY(Core::MappedFile::map_from_fd_and_close(fd, path)); - if (auto decoder = ImageDecoder::try_create_for_raw_bytes_with_known_path(path, file->bytes())) { + auto mime_type = Core::guess_mime_type_based_on_filename(path); + if (auto decoder = ImageDecoder::try_create_for_raw_bytes(file->bytes(), mime_type)) { auto frame = TRY(decoder->frame(0)); if (auto& bitmap = frame.image) return bitmap.release_nonnull(); diff --git a/Userland/Libraries/LibGfx/ImageDecoder.cpp b/Userland/Libraries/LibGfx/ImageDecoder.cpp index 9074172959..9d293317b3 100644 --- a/Userland/Libraries/LibGfx/ImageDecoder.cpp +++ b/Userland/Libraries/LibGfx/ImageDecoder.cpp @@ -69,21 +69,12 @@ static OwnPtr<ImageDecoderPlugin> probe_and_sniff_for_appropriate_plugin(Readonl return {}; } -RefPtr<ImageDecoder> ImageDecoder::try_create_for_raw_bytes(ReadonlyBytes bytes) +static OwnPtr<ImageDecoderPlugin> probe_and_sniff_for_appropriate_plugin_with_known_mime_type(StringView mime_type, ReadonlyBytes bytes) { - OwnPtr<ImageDecoderPlugin> plugin = probe_and_sniff_for_appropriate_plugin(bytes); - if (!plugin) - return {}; - return adopt_ref_if_nonnull(new (nothrow) ImageDecoder(plugin.release_nonnull())); -} - -static OwnPtr<ImageDecoderPlugin> probe_and_sniff_for_appropriate_plugin_with_known_path(StringView path, ReadonlyBytes bytes) -{ - LexicalPath lexical_mapped_file_path(path); auto* data = bytes.data(); auto size = bytes.size(); OwnPtr<ImageDecoderPlugin> plugin; - if (lexical_mapped_file_path.extension() == "tga"sv) { + if (mime_type == "image/x-targa"sv) { plugin = make<TGAImageDecoderPlugin>(data, size); if (plugin->sniff()) return plugin; @@ -91,11 +82,18 @@ static OwnPtr<ImageDecoderPlugin> probe_and_sniff_for_appropriate_plugin_with_kn return {}; } -RefPtr<ImageDecoder> ImageDecoder::try_create_for_raw_bytes_with_known_path(StringView path, ReadonlyBytes bytes) +RefPtr<ImageDecoder> ImageDecoder::try_create_for_raw_bytes(ReadonlyBytes bytes, Optional<DeprecatedString> mime_type) { - OwnPtr<ImageDecoderPlugin> plugin = probe_and_sniff_for_appropriate_plugin_with_known_path(path, bytes); - if (!plugin) - return try_create_for_raw_bytes(bytes); + OwnPtr<ImageDecoderPlugin> plugin = probe_and_sniff_for_appropriate_plugin(bytes); + if (!plugin) { + if (mime_type.has_value()) { + plugin = probe_and_sniff_for_appropriate_plugin_with_known_mime_type(mime_type.value(), bytes); + if (!plugin) + return {}; + } else { + return {}; + } + } return adopt_ref_if_nonnull(new (nothrow) ImageDecoder(plugin.release_nonnull())); } diff --git a/Userland/Libraries/LibGfx/ImageDecoder.h b/Userland/Libraries/LibGfx/ImageDecoder.h index 5b0731b9a2..9d622ec8ac 100644 --- a/Userland/Libraries/LibGfx/ImageDecoder.h +++ b/Userland/Libraries/LibGfx/ImageDecoder.h @@ -47,8 +47,7 @@ protected: class ImageDecoder : public RefCounted<ImageDecoder> { public: - static RefPtr<ImageDecoder> try_create_for_raw_bytes(ReadonlyBytes); - static RefPtr<ImageDecoder> try_create_for_raw_bytes_with_known_path(StringView path, ReadonlyBytes); + static RefPtr<ImageDecoder> try_create_for_raw_bytes(ReadonlyBytes, Optional<DeprecatedString> mime_type = {}); ~ImageDecoder() = default; IntSize size() const { return m_plugin->size(); } diff --git a/Userland/Libraries/LibImageDecoderClient/Client.cpp b/Userland/Libraries/LibImageDecoderClient/Client.cpp index abb151c279..63e1216d00 100644 --- a/Userland/Libraries/LibImageDecoderClient/Client.cpp +++ b/Userland/Libraries/LibImageDecoderClient/Client.cpp @@ -20,7 +20,7 @@ void Client::die() on_death(); } -Optional<DecodedImage> Client::decode_image_with_known_path(DeprecatedString const& path, ReadonlyBytes encoded_data) +Optional<DecodedImage> Client::decode_image(ReadonlyBytes encoded_data, Optional<DeprecatedString> mime_type) { if (encoded_data.is_empty()) return {}; @@ -33,44 +33,7 @@ Optional<DecodedImage> Client::decode_image_with_known_path(DeprecatedString con auto encoded_buffer = encoded_buffer_or_error.release_value(); memcpy(encoded_buffer.data<void>(), encoded_data.data(), encoded_data.size()); - auto response_or_error = try_decode_image_with_known_path(path, move(encoded_buffer)); - - if (response_or_error.is_error()) { - dbgln("ImageDecoder died heroically"); - return {}; - } - - auto& response = response_or_error.value(); - - if (response.bitmaps().is_empty()) - return {}; - - DecodedImage image; - image.is_animated = response.is_animated(); - image.loop_count = response.loop_count(); - image.frames.resize(response.bitmaps().size()); - for (size_t i = 0; i < image.frames.size(); ++i) { - auto& frame = image.frames[i]; - frame.bitmap = response.bitmaps()[i].bitmap(); - frame.duration = response.durations()[i]; - } - return image; -} - -Optional<DecodedImage> Client::decode_image(ReadonlyBytes encoded_data) -{ - if (encoded_data.is_empty()) - return {}; - - auto encoded_buffer_or_error = Core::AnonymousBuffer::create_with_size(encoded_data.size()); - if (encoded_buffer_or_error.is_error()) { - dbgln("Could not allocate encoded buffer"); - return {}; - } - auto encoded_buffer = encoded_buffer_or_error.release_value(); - - memcpy(encoded_buffer.data<void>(), encoded_data.data(), encoded_data.size()); - auto response_or_error = try_decode_image(move(encoded_buffer)); + auto response_or_error = try_decode_image(move(encoded_buffer), mime_type); if (response_or_error.is_error()) { dbgln("ImageDecoder died heroically"); diff --git a/Userland/Libraries/LibImageDecoderClient/Client.h b/Userland/Libraries/LibImageDecoderClient/Client.h index 4e15e9ea2e..5464fed0e7 100644 --- a/Userland/Libraries/LibImageDecoderClient/Client.h +++ b/Userland/Libraries/LibImageDecoderClient/Client.h @@ -30,8 +30,7 @@ class Client final IPC_CLIENT_CONNECTION(Client, "/tmp/session/%sid/portal/image"sv); public: - Optional<DecodedImage> decode_image(ReadonlyBytes); - Optional<DecodedImage> decode_image_with_known_path(DeprecatedString const& path, ReadonlyBytes); + Optional<DecodedImage> decode_image(ReadonlyBytes, Optional<DeprecatedString> mime_type = {}); Function<void()> on_death; |