mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 09:07:35 +00:00
LibGfx/JPEG: Expose the Exif metadata
The Exif metadata is contained in the APP1 segment. We only need to call the TIFF decoder to get the metadata back :^).
This commit is contained in:
parent
f6f647bf13
commit
6eb574a2b6
2 changed files with 36 additions and 0 deletions
|
@ -18,6 +18,8 @@
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibGfx/ImageFormats/JPEGLoader.h>
|
#include <LibGfx/ImageFormats/JPEGLoader.h>
|
||||||
#include <LibGfx/ImageFormats/JPEGShared.h>
|
#include <LibGfx/ImageFormats/JPEGShared.h>
|
||||||
|
#include <LibGfx/ImageFormats/TIFFLoader.h>
|
||||||
|
#include <LibGfx/ImageFormats/TIFFMetadata.h>
|
||||||
|
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
|
||||||
|
@ -466,6 +468,8 @@ struct JPEGLoadingContext {
|
||||||
|
|
||||||
Optional<ColorTransform> color_transform {};
|
Optional<ColorTransform> color_transform {};
|
||||||
|
|
||||||
|
OwnPtr<ExifMetadata> exif_metadata {};
|
||||||
|
|
||||||
Optional<ICCMultiChunkState> icc_multi_chunk_state;
|
Optional<ICCMultiChunkState> icc_multi_chunk_state;
|
||||||
Optional<ByteBuffer> icc_data;
|
Optional<ByteBuffer> icc_data;
|
||||||
};
|
};
|
||||||
|
@ -1163,6 +1167,26 @@ static ErrorOr<void> read_colour_encoding(JPEGStream& stream, [[maybe_unused]] J
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ErrorOr<void> read_exif(JPEGStream& stream, JPEGLoadingContext& context, int bytes_to_read)
|
||||||
|
{
|
||||||
|
// This refers to Exif's specification, see TIFFLoader for more information.
|
||||||
|
// 4.7.2.2. - APP1 internal structure
|
||||||
|
if (bytes_to_read <= 1) {
|
||||||
|
TRY(stream.discard(bytes_to_read));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard padding byte
|
||||||
|
TRY(stream.discard(1));
|
||||||
|
|
||||||
|
auto exif_buffer = TRY(ByteBuffer::create_uninitialized(bytes_to_read - 1));
|
||||||
|
TRY(stream.read_until_filled(exif_buffer));
|
||||||
|
|
||||||
|
context.exif_metadata = TRY(TIFFImageDecoderPlugin::read_exif_metadata(exif_buffer));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
static ErrorOr<void> read_app_marker(JPEGStream& stream, JPEGLoadingContext& context, int app_marker_number)
|
static ErrorOr<void> read_app_marker(JPEGStream& stream, JPEGLoadingContext& context, int app_marker_number)
|
||||||
{
|
{
|
||||||
// B.2.4.6 - Application data syntax
|
// B.2.4.6 - Application data syntax
|
||||||
|
@ -1187,6 +1211,8 @@ static ErrorOr<void> read_app_marker(JPEGStream& stream, JPEGLoadingContext& con
|
||||||
|
|
||||||
auto app_id = TRY(builder.to_string());
|
auto app_id = TRY(builder.to_string());
|
||||||
|
|
||||||
|
if (app_marker_number == 1 && app_id == "Exif"sv)
|
||||||
|
return read_exif(stream, context, bytes_to_read);
|
||||||
if (app_marker_number == 2 && app_id == "ICC_PROFILE"sv)
|
if (app_marker_number == 2 && app_id == "ICC_PROFILE"sv)
|
||||||
return read_icc_profile(stream, context, bytes_to_read);
|
return read_icc_profile(stream, context, bytes_to_read);
|
||||||
if (app_marker_number == 14 && app_id == "Adobe"sv)
|
if (app_marker_number == 14 && app_id == "Adobe"sv)
|
||||||
|
@ -2006,6 +2032,13 @@ ErrorOr<ImageFrameDescriptor> JPEGImageDecoderPlugin::frame(size_t index, Option
|
||||||
return ImageFrameDescriptor { m_context->bitmap, 0 };
|
return ImageFrameDescriptor { m_context->bitmap, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<Metadata const&> JPEGImageDecoderPlugin::metadata()
|
||||||
|
{
|
||||||
|
if (m_context->exif_metadata)
|
||||||
|
return *m_context->exif_metadata;
|
||||||
|
return OptionalNone {};
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<Optional<ReadonlyBytes>> JPEGImageDecoderPlugin::icc_data()
|
ErrorOr<Optional<ReadonlyBytes>> JPEGImageDecoderPlugin::icc_data()
|
||||||
{
|
{
|
||||||
if (m_context->icc_data.has_value())
|
if (m_context->icc_data.has_value())
|
||||||
|
|
|
@ -37,6 +37,9 @@ public:
|
||||||
virtual IntSize size() override;
|
virtual IntSize size() override;
|
||||||
|
|
||||||
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index, Optional<IntSize> ideal_size = {}) override;
|
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index, Optional<IntSize> ideal_size = {}) override;
|
||||||
|
|
||||||
|
virtual Optional<Metadata const&> metadata() override;
|
||||||
|
|
||||||
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;
|
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;
|
||||||
|
|
||||||
virtual NaturalFrameFormat natural_frame_format() const override;
|
virtual NaturalFrameFormat natural_frame_format() const override;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue