mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-23 01:32:14 -05:00
LibGfx/PNG: Read metadata from the eXIf chunk
The test image comes from this WPT test: http://wpt.live/png/exif-chunk.html
This commit is contained in:
parent
f28bb90d9b
commit
09f4032eeb
Notes:
sideshowbarker
2024-07-16 20:08:14 +09:00
Author: https://github.com/LucasChollet Commit: https://github.com/SerenityOS/serenity/commit/09f4032eeb Pull-request: https://github.com/SerenityOS/serenity/pull/24429 Reviewed-by: https://github.com/AtkinsSJ Reviewed-by: https://github.com/nico ✅
4 changed files with 33 additions and 0 deletions
|
@ -25,6 +25,7 @@
|
|||
#include <LibGfx/ImageFormats/QMArithmeticDecoder.h>
|
||||
#include <LibGfx/ImageFormats/TGALoader.h>
|
||||
#include <LibGfx/ImageFormats/TIFFLoader.h>
|
||||
#include <LibGfx/ImageFormats/TIFFMetadata.h>
|
||||
#include <LibGfx/ImageFormats/TinyVGLoader.h>
|
||||
#include <LibGfx/ImageFormats/WebPLoader.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
@ -768,6 +769,18 @@ TEST_CASE(test_png)
|
|||
TRY_OR_FAIL(expect_single_frame(*plugin_decoder));
|
||||
}
|
||||
|
||||
TEST_CASE(test_exif)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("png/exif.png"sv)));
|
||||
EXPECT(Gfx::PNGImageDecoderPlugin::sniff(file->bytes()));
|
||||
auto plugin_decoder = TRY_OR_FAIL(Gfx::PNGImageDecoderPlugin::create(file->bytes()));
|
||||
|
||||
TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 100, 200 }));
|
||||
EXPECT(plugin_decoder->metadata().has_value());
|
||||
auto const& exif_metadata = static_cast<Gfx::ExifMetadata const&>(plugin_decoder->metadata().value());
|
||||
EXPECT_EQ(*exif_metadata.orientation(), Gfx::TIFF::Orientation::Rotate90Clockwise);
|
||||
}
|
||||
|
||||
TEST_CASE(test_png_malformed_frame)
|
||||
{
|
||||
Array test_inputs = {
|
||||
|
|
BIN
Tests/LibGfx/test-inputs/png/exif.png
Normal file
BIN
Tests/LibGfx/test-inputs/png/exif.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 329 B |
|
@ -11,6 +11,8 @@
|
|||
#include <AK/Vector.h>
|
||||
#include <LibCompress/Zlib.h>
|
||||
#include <LibGfx/ImageFormats/PNGLoader.h>
|
||||
#include <LibGfx/ImageFormats/TIFFLoader.h>
|
||||
#include <LibGfx/ImageFormats/TIFFMetadata.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
@ -198,6 +200,8 @@ struct PNGLoadingContext {
|
|||
Optional<ByteBuffer> decompressed_icc_profile;
|
||||
Optional<RenderingIntent> sRGB_rendering_intent;
|
||||
|
||||
OwnPtr<ExifMetadata> exif_metadata;
|
||||
|
||||
Checked<int> compute_row_size_for_width(int width)
|
||||
{
|
||||
Checked<int> row_size = width;
|
||||
|
@ -1168,6 +1172,12 @@ static ErrorOr<void> process_fdAT(ReadonlyBytes data, PNGLoadingContext& context
|
|||
return {};
|
||||
}
|
||||
|
||||
static ErrorOr<void> process_eXIf(ReadonlyBytes bytes, PNGLoadingContext& context)
|
||||
{
|
||||
context.exif_metadata = TRY(TIFFImageDecoderPlugin::read_exif_metadata(bytes));
|
||||
return {};
|
||||
}
|
||||
|
||||
static void process_IEND(ReadonlyBytes, PNGLoadingContext& context)
|
||||
{
|
||||
// https://www.w3.org/TR/png/#11IEND
|
||||
|
@ -1235,6 +1245,8 @@ static ErrorOr<void> process_chunk(Streamer& streamer, PNGLoadingContext& contex
|
|||
return process_fcTL(chunk_data, context);
|
||||
if (chunk_type == "fdAT"sv)
|
||||
return process_fdAT(chunk_data, context);
|
||||
if (chunk_type == "eXIf"sv)
|
||||
return process_eXIf(chunk_data, context);
|
||||
if (chunk_type == "IEND"sv)
|
||||
process_IEND(chunk_data, context);
|
||||
return {};
|
||||
|
@ -1438,6 +1450,13 @@ ErrorOr<ImageFrameDescriptor> PNGImageDecoderPlugin::frame(size_t index, Optiona
|
|||
return descriptor;
|
||||
}
|
||||
|
||||
Optional<Metadata const&> PNGImageDecoderPlugin::metadata()
|
||||
{
|
||||
if (m_context->exif_metadata)
|
||||
return *m_context->exif_metadata;
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
ErrorOr<Optional<ReadonlyBytes>> PNGImageDecoderPlugin::icc_data()
|
||||
{
|
||||
if (!decode_png_chunks(*m_context))
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
virtual size_t frame_count() override;
|
||||
virtual size_t first_animated_frame_index() 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;
|
||||
|
||||
static void unfilter_scanline(PNG::FilterType filter, Bytes scanline_data, ReadonlyBytes previous_scanlines_data, u8 bytes_per_complete_pixel);
|
||||
|
|
Loading…
Reference in a new issue