summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2023-01-23 11:00:22 -0500
committerLinus Groh <mail@linusgroh.de>2023-01-23 18:09:23 +0000
commit97568427349b5c7c8632912352e55dd19b579198 (patch)
tree8dc2b88ad80e7626ff40127929ae006645774575
parent9c5820326d62f52b408d8f4e271d8360108686f2 (diff)
downloadserenity-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.cpp24
-rw-r--r--Userland/Libraries/LibGfx/ICCProfile.h22
-rw-r--r--Userland/Utilities/icc.cpp19
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());