diff --git a/Userland/Libraries/LibGfx/ICCProfile.cpp b/Userland/Libraries/LibGfx/ICCProfile.cpp index b1527781ee..76963281cb 100644 --- a/Userland/Libraries/LibGfx/ICCProfile.cpp +++ b/Userland/Libraries/LibGfx/ICCProfile.cpp @@ -284,6 +284,12 @@ StringView rendering_intent_name(RenderingIntent rendering_intent) VERIFY_NOT_REACHED(); } +Flags::Flags() = default; +Flags::Flags(u32 bits) + : m_bits(bits) +{ +} + ErrorOr> Profile::try_load_from_externally_owned_memory(ReadonlyBytes bytes) { auto profile = adopt_ref(*new Profile()); @@ -298,6 +304,7 @@ ErrorOr> Profile::try_load_from_externally_owned_memory(R profile->m_device_class = TRY(parse_device_class(header)); profile->m_data_color_space = TRY(parse_data_color_space(header)); profile->m_creation_timestamp = TRY(parse_creation_date_time(header)); + profile->m_flags = Flags { header.profile_flags }; profile->m_rendering_intent = TRY(parse_rendering_intent(header)); return profile; diff --git a/Userland/Libraries/LibGfx/ICCProfile.h b/Userland/Libraries/LibGfx/ICCProfile.h index ae307a2868..11287bd375 100644 --- a/Userland/Libraries/LibGfx/ICCProfile.h +++ b/Userland/Libraries/LibGfx/ICCProfile.h @@ -84,6 +84,34 @@ enum class RenderingIntent { }; StringView rendering_intent_name(RenderingIntent); +// ICC v4, 7.2.11 Profile flags field +class Flags { +public: + Flags(); + + // "The profile flags field contains flags." + Flags(u32); + + u32 bits() const { return m_bits; } + + // "These can indicate various hints for the CMM such as distributed processing and caching options." + // "The least-significant 16 bits are reserved for the ICC." + u16 color_management_module_bits() const { return bits() >> 16; } + u16 icc_bits() const { return bits() & 0xff; } + + // "Bit position 0: Embedded profile (0 if not embedded, 1 if embedded in file)" + bool is_embedded_in_file() const { return (icc_bits() & 1) != 0; } + + // "Bit position 1: Profile cannot be used independently of the embedded colour data (set to 1 if true, 0 if false)" + // Double negation isn't unconfusing, so this function uses the inverted, positive sense. + bool can_be_used_independently_of_embedded_color_data() const { return (icc_bits() & 2) == 0; } + + static constexpr u32 KnownBitsMask = 3; + +private: + u32 m_bits = 0; +}; + class Profile : public RefCounted { public: static ErrorOr> try_load_from_externally_owned_memory(ReadonlyBytes bytes); @@ -92,6 +120,7 @@ public: DeviceClass device_class() const { return m_device_class; } ColorSpace data_color_space() const { return m_data_color_space; } time_t creation_timestamp() const { return m_creation_timestamp; } + Flags flags() const { return m_flags; } RenderingIntent rendering_intent() const { return m_rendering_intent; } private: @@ -99,6 +128,7 @@ private: DeviceClass m_device_class; ColorSpace m_data_color_space; time_t m_creation_timestamp; + Flags m_flags; RenderingIntent m_rendering_intent; }; diff --git a/Userland/Utilities/icc.cpp b/Userland/Utilities/icc.cpp index cc75432c3c..9fad397005 100644 --- a/Userland/Utilities/icc.cpp +++ b/Userland/Utilities/icc.cpp @@ -25,6 +25,16 @@ ErrorOr serenity_main(Main::Arguments arguments) outln("device class: {}", Gfx::ICC::device_class_name(profile->device_class())); outln("data color space: {}", Gfx::ICC::color_space_name(profile->data_color_space())); outln("creation date and time: {}", Core::DateTime::from_timestamp(profile->creation_timestamp()).to_deprecated_string()); + + auto flags = profile->flags(); + outln("flags: 0x{:08x}", flags.bits()); + outln(" embedded in file: {}", flags.is_embedded_in_file() ? "yes" : "no"); + outln(" can be used independently of embedded color data: {}", flags.can_be_used_independently_of_embedded_color_data() ? "yes" : "no"); + if (auto unknown_icc_bits = flags.icc_bits() & ~Gfx::ICC::Flags::KnownBitsMask) + outln(" other unknown ICC bits: 0x{:04x}", unknown_icc_bits); + if (auto color_management_module_bits = flags.color_management_module_bits()) + outln(" CMM bits: 0x{:04x}", color_management_module_bits); + outln("rendering intent: {}", Gfx::ICC::rendering_intent_name(profile->rendering_intent())); return 0;