diff --git a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp index 78f87d3b0c..e1c96aa05f 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp @@ -41,6 +41,7 @@ public: ErrorOr decode_frame() { + TRY(ensure_baseline_tags_presence(m_metadata)); auto maybe_error = decode_frame_impl(); if (maybe_error.is_error()) { diff --git a/Userland/Libraries/LibGfx/TIFFGenerator.py b/Userland/Libraries/LibGfx/TIFFGenerator.py index c655dca594..0fcaffbadd 100755 --- a/Userland/Libraries/LibGfx/TIFFGenerator.py +++ b/Userland/Libraries/LibGfx/TIFFGenerator.py @@ -96,7 +96,7 @@ class ExtraSample(EnumWithExportName): UnassociatedAlpha = 2 -tag_fields = ['id', 'types', 'counts', 'default', 'name', 'associated_enum'] +tag_fields = ['id', 'types', 'counts', 'default', 'name', 'associated_enum', 'is_required'] Tag = namedtuple( 'Tag', @@ -106,16 +106,17 @@ Tag = namedtuple( # FIXME: Some tag have only a few allowed values, we should ensure that known_tags: List[Tag] = [ - Tag('256', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageWidth"), - Tag('257', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageHeight"), - Tag('258', [TIFFType.UnsignedShort], [], None, "BitsPerSample"), - Tag('259', [TIFFType.UnsignedShort], [1], None, "Compression", Compression), - Tag('262', [TIFFType.UnsignedShort], [1], None, "PhotometricInterpretation", PhotometricInterpretation), - Tag('273', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripOffsets"), + Tag('256', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageWidth", is_required=True), + Tag('257', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "ImageHeight", is_required=True), + Tag('258', [TIFFType.UnsignedShort], [], None, "BitsPerSample", is_required=True), + Tag('259', [TIFFType.UnsignedShort], [1], None, "Compression", Compression, is_required=True), + Tag('262', [TIFFType.UnsignedShort], [1], None, "PhotometricInterpretation", + PhotometricInterpretation, is_required=True), + Tag('273', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripOffsets", is_required=True), Tag('274', [TIFFType.UnsignedShort], [1], Orientation.Default, "Orientation", Orientation), - Tag('277', [TIFFType.UnsignedShort], [1], None, "SamplesPerPixel"), - Tag('278', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "RowsPerStrip"), - Tag('279', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripByteCounts"), + Tag('277', [TIFFType.UnsignedShort], [1], None, "SamplesPerPixel", is_required=True), + Tag('278', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "RowsPerStrip", is_required=True), + Tag('279', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripByteCounts", is_required=True), Tag('282', [TIFFType.UnsignedRational], [], None, "XResolution"), Tag('283', [TIFFType.UnsignedRational], [], None, "YResolution"), Tag('284', [TIFFType.UnsignedShort], [], PlanarConfiguration.Chunky, "PlanarConfiguration", PlanarConfiguration), @@ -133,6 +134,8 @@ HANDLE_TAG_SIGNATURE_TEMPLATE = ("ErrorOr {namespace}handle_tag(Metadata& HANDLE_TAG_SIGNATURE = HANDLE_TAG_SIGNATURE_TEMPLATE.format(namespace="") HANDLE_TAG_SIGNATURE_TIFF_NAMESPACE = HANDLE_TAG_SIGNATURE_TEMPLATE.format(namespace="TIFF::") +ENSURE_BASELINE_TAG_PRESENCE = "ErrorOr ensure_baseline_tags_presence(Metadata const& metadata)" + LICENSE = R"""/* * Copyright (c) 2023, Lucas Chollet * @@ -352,6 +355,7 @@ using Value = Variant, i32, Rational {export_enum_to_string_converter([tag.associated_enum for tag in known_tags if tag.associated_enum] + [TIFFType])} {HANDLE_TAG_SIGNATURE}; +{ENSURE_BASELINE_TAG_PRESENCE}; }} @@ -434,6 +438,10 @@ def generate_tag_handler_file(tags: List[Tag]) -> str: name_for_enum_tag_value(static_cast<{tag.associated_enum.export_name()}>(v.get()))));""" for tag in tags if tag.associated_enum]) + ensure_tag_presence = '\n'.join([fR""" if (!metadata.{pascal_case_to_snake_case(tag.name)}().has_value()) + return Error::from_string_literal("Unable to decode image, missing required tag {tag.name}."); +""" for tag in filter(lambda tag: tag.is_required, known_tags)]) + output = fR"""{LICENSE} #include @@ -467,6 +475,13 @@ static String value_formatter(u32 tag_id, Value const& v) {{ return MUST(builder.to_string()); }} +{ENSURE_BASELINE_TAG_PRESENCE} +{{ +{ensure_tag_presence} + return {{}}; +}} + + {HANDLE_TAG_SIGNATURE} {{ switch (tag) {{