diff --git a/Userland/Applications/ImageViewer/ViewWidget.cpp b/Userland/Applications/ImageViewer/ViewWidget.cpp index ec4cadf384..c65a23518a 100644 --- a/Userland/Applications/ImageViewer/ViewWidget.cpp +++ b/Userland/Applications/ImageViewer/ViewWidget.cpp @@ -246,7 +246,7 @@ ErrorOr ViewWidget::try_open_file(String const& path, Core::File& file) frames.ensure_capacity(decoded_image->frames.size()); for (u32 i = 0; i < decoded_image->frames.size(); i++) { auto& frame_data = decoded_image->frames[i]; - frames.unchecked_append({ BitmapImage::create(frame_data.bitmap), int(frame_data.duration) }); + frames.unchecked_append({ BitmapImage::create(frame_data.bitmap, decoded_image->scale), int(frame_data.duration) }); } } diff --git a/Userland/Applications/ImageViewer/ViewWidget.h b/Userland/Applications/ImageViewer/ViewWidget.h index e509cb8efb..962f0843b4 100644 --- a/Userland/Applications/ImageViewer/ViewWidget.h +++ b/Userland/Applications/ImageViewer/ViewWidget.h @@ -66,9 +66,9 @@ private: class BitmapImage final : public Image { public: - static NonnullRefPtr create(Gfx::Bitmap& bitmap) { return adopt_ref(*new BitmapImage(bitmap)); } + static NonnullRefPtr create(Gfx::Bitmap& bitmap, Gfx::FloatPoint scale) { return adopt_ref(*new BitmapImage(bitmap, scale)); } - virtual Gfx::IntSize size() const override { return m_bitmap->size(); } + virtual Gfx::IntSize size() const override { return { round(m_bitmap->size().width() * m_scale.x()), round(m_bitmap->size().height() * m_scale.y()) }; } virtual void flip(Gfx::Orientation) override; virtual void rotate(Gfx::RotationDirection) override; @@ -81,12 +81,14 @@ public: } private: - BitmapImage(Gfx::Bitmap& bitmap) + BitmapImage(Gfx::Bitmap& bitmap, Gfx::FloatPoint scale) : m_bitmap(bitmap) + , m_scale(scale) { } NonnullRefPtr m_bitmap; + Gfx::FloatPoint m_scale; }; class ViewWidget final : public GUI::AbstractZoomPanWidget { diff --git a/Userland/Libraries/LibImageDecoderClient/Client.cpp b/Userland/Libraries/LibImageDecoderClient/Client.cpp index 0aa014b987..ab27b085bd 100644 --- a/Userland/Libraries/LibImageDecoderClient/Client.cpp +++ b/Userland/Libraries/LibImageDecoderClient/Client.cpp @@ -48,6 +48,7 @@ Optional Client::decode_image(ReadonlyBytes encoded_data, Optional DecodedImage image; image.is_animated = response.is_animated(); image.loop_count = response.loop_count(); + image.scale = response.scale(); image.frames.ensure_capacity(response.bitmaps().size()); auto bitmaps = response.take_bitmaps(); for (size_t i = 0; i < bitmaps.size(); ++i) { diff --git a/Userland/Libraries/LibImageDecoderClient/Client.h b/Userland/Libraries/LibImageDecoderClient/Client.h index ed163252c5..a2a3ebaf54 100644 --- a/Userland/Libraries/LibImageDecoderClient/Client.h +++ b/Userland/Libraries/LibImageDecoderClient/Client.h @@ -20,6 +20,7 @@ struct Frame { struct DecodedImage { bool is_animated { false }; + Gfx::FloatPoint scale { 1, 1 }; u32 loop_count { 0 }; Vector frames; }; diff --git a/Userland/Services/ImageDecoder/ConnectionFromClient.cpp b/Userland/Services/ImageDecoder/ConnectionFromClient.cpp index 54ad58adcd..acb5d7f0b0 100644 --- a/Userland/Services/ImageDecoder/ConnectionFromClient.cpp +++ b/Userland/Services/ImageDecoder/ConnectionFromClient.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace ImageDecoder { @@ -37,7 +38,7 @@ static void decode_image_to_bitmaps_and_durations_with_decoder(Gfx::ImageDecoder } } -static void decode_image_to_details(Core::AnonymousBuffer const& encoded_buffer, Optional ideal_size, Optional const& known_mime_type, bool& is_animated, u32& loop_count, Vector& bitmaps, Vector& durations) +static void decode_image_to_details(Core::AnonymousBuffer const& encoded_buffer, Optional ideal_size, Optional const& known_mime_type, bool& is_animated, u32& loop_count, Vector& bitmaps, Vector& durations, Gfx::FloatPoint& scale) { VERIFY(bitmaps.size() == 0); VERIFY(durations.size() == 0); @@ -54,6 +55,19 @@ static void decode_image_to_details(Core::AnonymousBuffer const& encoded_buffer, } is_animated = decoder->is_animated(); loop_count = decoder->loop_count(); + + if (auto maybe_metadata = decoder->metadata(); maybe_metadata.has_value() && is(*maybe_metadata)) { + auto const& exif = static_cast(maybe_metadata.value()); + if (exif.x_resolution().has_value() && exif.y_resolution().has_value()) { + auto const x_resolution = exif.x_resolution()->as_double(); + auto const y_resolution = exif.y_resolution()->as_double(); + if (x_resolution < y_resolution) + scale.set_y(x_resolution / y_resolution); + else + scale.set_x(y_resolution / x_resolution); + } + } + decode_image_to_bitmaps_and_durations_with_decoder(*decoder, ideal_size, bitmaps, durations); } @@ -66,10 +80,11 @@ Messages::ImageDecoderServer::DecodeImageResponse ConnectionFromClient::decode_i bool is_animated = false; u32 loop_count = 0; + Gfx::FloatPoint scale { 1, 1 }; Vector bitmaps; Vector durations; - decode_image_to_details(encoded_buffer, ideal_size, mime_type, is_animated, loop_count, bitmaps, durations); - return { is_animated, loop_count, bitmaps, durations }; + decode_image_to_details(encoded_buffer, ideal_size, mime_type, is_animated, loop_count, bitmaps, durations, scale); + return { is_animated, loop_count, bitmaps, durations, scale }; } } diff --git a/Userland/Services/ImageDecoder/ImageDecoderServer.ipc b/Userland/Services/ImageDecoder/ImageDecoderServer.ipc index 10e92fe8cd..2776417df0 100644 --- a/Userland/Services/ImageDecoder/ImageDecoderServer.ipc +++ b/Userland/Services/ImageDecoder/ImageDecoderServer.ipc @@ -3,5 +3,5 @@ endpoint ImageDecoderServer { - decode_image(Core::AnonymousBuffer data, Optional ideal_size, Optional mime_type) => (bool is_animated, u32 loop_count, Vector bitmaps, Vector durations) + decode_image(Core::AnonymousBuffer data, Optional ideal_size, Optional mime_type) => (bool is_animated, u32 loop_count, Vector bitmaps, Vector durations, Gfx::FloatPoint scale) }