From a43793ee0df37519d63562552abaed754a495649 Mon Sep 17 00:00:00 2001 From: Lucas CHOLLET Date: Sat, 3 Feb 2024 16:34:31 -0500 Subject: [PATCH] LibGfx/TIFF: Explore underlying Image File Directories Every TIFF containers is composed of a main IFD. Some entries of this one can be a pointer to a sub-IFD. We are now capable of exploring these underlying structures. Note that we don't do anything with them yet. --- .../Libraries/LibGfx/ImageFormats/TIFFLoader.cpp | 11 +++++++++-- Userland/Libraries/LibGfx/TIFFGenerator.py | 12 ++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp index 5b47182dca5f26..9eecea584e9aac 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp @@ -453,7 +453,6 @@ class TIFFLoadingContext { m_next_ifd = Optional { next_block_position }; else m_next_ifd = OptionalNone {}; - dbgln_if(TIFF_DEBUG, "Setting image file directory pointer to {}", m_next_ifd); return {}; } @@ -491,6 +490,8 @@ class TIFFLoadingContext { if (!m_next_ifd.has_value()) return Error::from_string_literal("TIFFImageDecoderPlugin: Missing an Image File Directory"); + dbgln_if(TIFF_DEBUG, "Reading image file directory at offset {}", m_next_ifd); + TRY(m_stream->seek(m_next_ifd.value())); auto const number_of_field = TRY(read_value()); @@ -597,7 +598,13 @@ class TIFFLoadingContext { return read_tiff_value(type, count, offset); }())); - TRY(handle_tag(m_metadata, tag, type, count, move(tiff_value))); + auto subifd_handler = [&](u32 ifd_offset) -> ErrorOr { + m_next_ifd = ifd_offset; + TRY(read_next_image_file_directory()); + return {}; + }; + + TRY(handle_tag(move(subifd_handler), m_metadata, tag, type, count, move(tiff_value))); return {}; } diff --git a/Userland/Libraries/LibGfx/TIFFGenerator.py b/Userland/Libraries/LibGfx/TIFFGenerator.py index 32766f25403ef6..eaacdb5672fa41 100755 --- a/Userland/Libraries/LibGfx/TIFFGenerator.py +++ b/Userland/Libraries/LibGfx/TIFFGenerator.py @@ -148,8 +148,9 @@ class ExtraSample(EnumWithExportName): Tag('34675', [TIFFType.Undefined], [], None, "ICCProfile"), ] -HANDLE_TAG_SIGNATURE_TEMPLATE = ("ErrorOr {namespace}handle_tag(ExifMetadata& metadata, u16 tag," - " {namespace}Type type, u32 count, Vector<{namespace}Value>&& value)") +HANDLE_TAG_SIGNATURE_TEMPLATE = ("ErrorOr {namespace}handle_tag(Function(u32)>&& subifd_handler, " + "ExifMetadata& metadata, u16 tag, {namespace}Type type, u32 count, " + "Vector<{namespace}Value>&& value)") HANDLE_TAG_SIGNATURE = HANDLE_TAG_SIGNATURE_TEMPLATE.format(namespace="") HANDLE_TAG_SIGNATURE_TIFF_NAMESPACE = HANDLE_TAG_SIGNATURE_TEMPLATE.format(namespace="TIFF::") @@ -478,6 +479,12 @@ def generate_tag_handler(tag: Tag) -> str: }} """ + handle_subifd = '' + if TIFFType.IFD in tag.types: + if tag.counts != [1]: + raise RuntimeError("Accessing `value[0]` in the C++ code might fail!") + handle_subifd = f'TRY(subifd_handler(value[0].get<{tiff_type_to_cpp(TIFFType.IFD)}>()));' + output = fR""" case {tag.id}: // {tag.name} @@ -485,6 +492,7 @@ def generate_tag_handler(tag: Tag) -> str: {pre_condition} {check_value} + {handle_subifd} metadata.add_entry("{tag.name}"sv, move(value)); break; """