diff --git a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp index 631e0e7327..e829735174 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp @@ -346,8 +346,13 @@ private: switch (type) { case Type::Byte: - case Type::Undefined: - return read_every_values.template operator()(); + case Type::Undefined: { + Vector result; + auto buffer = TRY(ByteBuffer::create_uninitialized(count)); + TRY(m_stream->read_until_filled(buffer)); + result.append(move(buffer)); + return result; + } case Type::ASCII: case Type::UTF8: { Vector result; @@ -397,6 +402,9 @@ private: if constexpr (TIFF_DEBUG) { if (tiff_value.size() == 1) { tiff_value[0].visit( + [&](ByteBuffer& value) { + dbgln("Read tag({}), type({}): size {}", tag, to_underlying(type), value.size()); + }, [&](auto const& value) { dbgln("Read tag({}), type({}): {}", tag, to_underlying(type), value); }); @@ -404,6 +412,9 @@ private: dbg("Read tag({}), type({}): [", tag, to_underlying(type)); for (u32 i = 0; i < tiff_value.size(); ++i) { tiff_value[i].visit( + [&](ByteBuffer&) { + VERIFY_NOT_REACHED(); + }, [&](auto const& value) { dbg("{}", value); }); diff --git a/Userland/Libraries/LibGfx/TIFFGenerator.py b/Userland/Libraries/LibGfx/TIFFGenerator.py index 490a1bbe81..42a7002d0c 100755 --- a/Userland/Libraries/LibGfx/TIFFGenerator.py +++ b/Userland/Libraries/LibGfx/TIFFGenerator.py @@ -103,6 +103,8 @@ def tiff_type_to_cpp(t: TIFFType, without_promotion: bool = False) -> str: # Note that the Value<> type doesn't include u16 for this reason if not without_promotion: t = promote_type(t) + if t == TIFFType.Undefined: + return 'ByteBuffer' if t == TIFFType.UnsignedShort: return 'u16' if t == TIFFType.UnsignedLong: @@ -110,6 +112,15 @@ def tiff_type_to_cpp(t: TIFFType, without_promotion: bool = False) -> str: raise RuntimeError(f'Type "{t}" not recognized, please update tiff_type_to_read_only_cpp()') +def is_container(t: TIFFType) -> bool: + """ + Some TIFF types are defined on the unit scale but are intended to be used within a collection. + An example of that are ASCII strings defined as N * byte. Let's intercept that and generate + a nice API instead of Vector. + """ + return t in [TIFFType.Byte, TIFFType.Undefined] + + def export_promoter() -> str: output = R"""template struct TypePromoter { @@ -137,7 +148,8 @@ def pascal_case_to_snake_case(name: str) -> str: def generate_getter(tag: Tag) -> str: - variant_inner_type = tiff_type_to_cpp(retrieve_biggest_type(tag.types)) + biggest_type = retrieve_biggest_type(tag.types) + variant_inner_type = tiff_type_to_cpp(biggest_type) extracted_value_template = f"(*possible_value)[{{}}].get<{variant_inner_type}>()" @@ -146,8 +158,10 @@ def generate_getter(tag: Tag) -> str: tag_final_type = f"TIFF::{tag.associated_enum.__name__}" extracted_value_template = f"static_cast<{tag_final_type}>({extracted_value_template})" - if len(tag.counts) == 1 and tag.counts[0] == 1: + if len(tag.counts) == 1 and tag.counts[0] == 1 or is_container(biggest_type): return_type = tag_final_type + if is_container(biggest_type): + return_type += ' const&' unpacked_if_needed = f"return {extracted_value_template.format(0)};" else: if len(tag.counts) == 1: @@ -231,7 +245,7 @@ struct Rational {{ {export_promoter()} // Note that u16 is not include on purpose -using Value = Variant, i32, Rational>; +using Value = Variant, i32, Rational>; {export_tag_related_enums(known_tags)}