summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2023-01-20 03:27:10 +0200
committerLinus Groh <mail@linusgroh.de>2023-01-20 15:13:31 +0000
commit6e6999ce5767121a6904b6c36454723e39b9bf24 (patch)
treea13426f1402eaa030397c3545b694ae3683f6f2d /Userland/Libraries
parentfedd18eb89db0f9a6b8047cd2a5a7d716cca9544 (diff)
downloadserenity-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.cpp4
-rw-r--r--Userland/Libraries/LibGfx/Bitmap.cpp4
-rw-r--r--Userland/Libraries/LibGfx/ImageDecoder.cpp28
-rw-r--r--Userland/Libraries/LibGfx/ImageDecoder.h3
-rw-r--r--Userland/Libraries/LibImageDecoderClient/Client.cpp41
-rw-r--r--Userland/Libraries/LibImageDecoderClient/Client.h3
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;