diff options
author | Nico Weber <thakis@chromium.org> | 2023-01-23 11:00:22 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-01-23 18:09:23 +0000 |
commit | 97568427349b5c7c8632912352e55dd19b579198 (patch) | |
tree | 8dc2b88ad80e7626ff40127929ae006645774575 | |
parent | 9c5820326d62f52b408d8f4e271d8360108686f2 (diff) | |
download | serenity-97568427349b5c7c8632912352e55dd19b579198.zip |
LibGfx+icc: Add ICCProfile support for s15Fixed16ArrayType and print it
This is the type of the chromaticAdaptationTag, which is a required tag
in v4 profiles for all non-DeviceLink profiles.
-rw-r--r-- | Userland/Libraries/LibGfx/ICCProfile.cpp | 24 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/ICCProfile.h | 22 | ||||
-rw-r--r-- | Userland/Utilities/icc.cpp | 19 |
3 files changed, 65 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGfx/ICCProfile.cpp b/Userland/Libraries/LibGfx/ICCProfile.cpp index 2b4bfb084d..7d6bf95b58 100644 --- a/Userland/Libraries/LibGfx/ICCProfile.cpp +++ b/Userland/Libraries/LibGfx/ICCProfile.cpp @@ -612,6 +612,28 @@ ErrorOr<NonnullRefPtr<MultiLocalizedUnicodeTagData>> MultiLocalizedUnicodeTagDat return adopt_ref(*new MultiLocalizedUnicodeTagData(offset, size, move(records))); } +ErrorOr<NonnullRefPtr<S15Fixed16ArrayTagData>> S15Fixed16ArrayTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size) +{ + // ICC v4, 10.22 s15Fixed16ArrayType + VERIFY(tag_type(bytes) == Type); + TRY(check_reserved(bytes)); + + // "This type represents an array of generic 4-byte (32-bit) fixed point quantity. The number of values is determined + // from the size of the tag." + size_t byte_size = bytes.size() - 8; + if (byte_size % sizeof(s15Fixed16Number) != 0) + return Error::from_string_literal("ICC::Profile: s15Fixed16ArrayType has wrong size"); + + size_t count = byte_size / sizeof(s15Fixed16Number); + BigEndian<s15Fixed16Number> const* raw_values = bit_cast<BigEndian<s15Fixed16Number> const*>(bytes.data() + 8); + Vector<S15Fixed16, 9> values; + TRY(values.try_resize(count)); + for (size_t i = 0; i < count; ++i) + values[i] = S15Fixed16::create_raw(raw_values[i]); + + return adopt_ref(*new S15Fixed16ArrayTagData(offset, size, move(values))); +} + ErrorOr<NonnullRefPtr<TextDescriptionTagData>> TextDescriptionTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size) { // ICC v2, 6.5.17 textDescriptionType @@ -850,6 +872,8 @@ ErrorOr<NonnullRefPtr<TagData>> Profile::read_tag(ReadonlyBytes bytes, Detail::T switch (type) { case MultiLocalizedUnicodeTagData::Type: return MultiLocalizedUnicodeTagData::from_bytes(tag_bytes, entry.offset_to_beginning_of_tag_data_element, entry.size_of_tag_data_element); + case S15Fixed16ArrayTagData::Type: + return S15Fixed16ArrayTagData::from_bytes(tag_bytes, entry.offset_to_beginning_of_tag_data_element, entry.size_of_tag_data_element); case TextDescriptionTagData::Type: return TextDescriptionTagData::from_bytes(tag_bytes, entry.offset_to_beginning_of_tag_data_element, entry.size_of_tag_data_element); case TextTagData::Type: diff --git a/Userland/Libraries/LibGfx/ICCProfile.h b/Userland/Libraries/LibGfx/ICCProfile.h index 3f3ae202cb..736b57035f 100644 --- a/Userland/Libraries/LibGfx/ICCProfile.h +++ b/Userland/Libraries/LibGfx/ICCProfile.h @@ -7,6 +7,7 @@ #pragma once #include <AK/Error.h> +#include <AK/FixedPoint.h> #include <AK/Format.h> #include <AK/HashMap.h> #include <AK/NonnullRefPtr.h> @@ -282,6 +283,27 @@ private: Vector<Record> m_records; }; +// ICC v4, 10.22 s15Fixed16ArrayType +class S15Fixed16ArrayTagData : public TagData { +public: + static constexpr TagTypeSignature Type { 0x73663332 }; // 'sf32' + + using S15Fixed16 = FixedPoint<16, i32>; + + static ErrorOr<NonnullRefPtr<S15Fixed16ArrayTagData>> from_bytes(ReadonlyBytes, u32 offset, u32 size); + + S15Fixed16ArrayTagData(u32 offset, u32 size, Vector<S15Fixed16, 9> values) + : TagData(offset, size, Type) + , m_values(move(values)) + { + } + + Vector<S15Fixed16, 9> const& values() const { return m_values; } + +private: + Vector<S15Fixed16, 9> m_values; +}; + // ICC v2, 6.5.17 textDescriptionType class TextDescriptionTagData : public TagData { public: diff --git a/Userland/Utilities/icc.cpp b/Userland/Utilities/icc.cpp index 7f38fd672c..a92ec51d4e 100644 --- a/Userland/Utilities/icc.cpp +++ b/Userland/Utilities/icc.cpp @@ -102,6 +102,25 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) record.iso_3166_1_country_code >> 8, record.iso_3166_1_country_code & 0xff, record.text); } + } else if (tag_data->type() == Gfx::ICC::S15Fixed16ArrayTagData::Type) { + // This tag can contain arbitrarily many fixed-point numbers, but in practice it's + // exclusively used for the 'chad' tag, where it always contains 9 values that + // represent a 3x3 matrix. So print the values in groups of 3. + auto& fixed_array = static_cast<Gfx::ICC::S15Fixed16ArrayTagData&>(*tag_data); + out(" ["); + int i = 0; + for (auto value : fixed_array.values()) { + if (i > 0) { + out(","); + if (i % 3 == 0) { + outln(); + out(" "); + } + } + out(" {}", value); + i++; + } + outln(" ]"); } else if (tag_data->type() == Gfx::ICC::TextDescriptionTagData::Type) { auto& text_description = static_cast<Gfx::ICC::TextDescriptionTagData&>(*tag_data); outln(" ascii: \"{}\"", text_description.ascii_description()); |