mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 03:34:57 +00:00
ImageViewer: Transform the image's dimension accordingly to the metadata
Exif metadata have two tags to store the pixel density along each axis. If both values are different and no action is taken, the resulting image will appear deformed. This commit scales the displayed bitmap accordingly to these tags in order to show the image in its intended shape. This unfortunately includes a lot of plumbing to get this information through IPC.
This commit is contained in:
parent
8dd887b3c8
commit
8e2102fb73
6 changed files with 27 additions and 8 deletions
|
@ -246,7 +246,7 @@ ErrorOr<void> 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) });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,9 +66,9 @@ private:
|
|||
|
||||
class BitmapImage final : public Image {
|
||||
public:
|
||||
static NonnullRefPtr<BitmapImage> create(Gfx::Bitmap& bitmap) { return adopt_ref(*new BitmapImage(bitmap)); }
|
||||
static NonnullRefPtr<BitmapImage> 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<Gfx::Bitmap> m_bitmap;
|
||||
Gfx::FloatPoint m_scale;
|
||||
};
|
||||
|
||||
class ViewWidget final : public GUI::AbstractZoomPanWidget {
|
||||
|
|
|
@ -48,6 +48,7 @@ Optional<DecodedImage> 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) {
|
||||
|
|
|
@ -20,6 +20,7 @@ struct Frame {
|
|||
|
||||
struct DecodedImage {
|
||||
bool is_animated { false };
|
||||
Gfx::FloatPoint scale { 1, 1 };
|
||||
u32 loop_count { 0 };
|
||||
Vector<Frame> frames;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <ImageDecoder/ImageDecoderClientEndpoint.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/ImageFormats/ImageDecoder.h>
|
||||
#include <LibGfx/ImageFormats/TIFFMetadata.h>
|
||||
|
||||
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<Gfx::IntSize> ideal_size, Optional<ByteString> const& known_mime_type, bool& is_animated, u32& loop_count, Vector<Gfx::ShareableBitmap>& bitmaps, Vector<u32>& durations)
|
||||
static void decode_image_to_details(Core::AnonymousBuffer const& encoded_buffer, Optional<Gfx::IntSize> ideal_size, Optional<ByteString> const& known_mime_type, bool& is_animated, u32& loop_count, Vector<Gfx::ShareableBitmap>& bitmaps, Vector<u32>& 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<Gfx::ExifMetadata>(*maybe_metadata)) {
|
||||
auto const& exif = static_cast<Gfx::ExifMetadata const&>(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<Gfx::ShareableBitmap> bitmaps;
|
||||
Vector<u32> 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 };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
endpoint ImageDecoderServer
|
||||
{
|
||||
decode_image(Core::AnonymousBuffer data, Optional<Gfx::IntSize> ideal_size, Optional<ByteString> mime_type) => (bool is_animated, u32 loop_count, Vector<Gfx::ShareableBitmap> bitmaps, Vector<u32> durations)
|
||||
decode_image(Core::AnonymousBuffer data, Optional<Gfx::IntSize> ideal_size, Optional<ByteString> mime_type) => (bool is_animated, u32 loop_count, Vector<Gfx::ShareableBitmap> bitmaps, Vector<u32> durations, Gfx::FloatPoint scale)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue