diff --git a/Userland/Libraries/LibGfx/ICCProfile.cpp b/Userland/Libraries/LibGfx/ICCProfile.cpp index 76963281cb..fd85534790 100644 --- a/Userland/Libraries/LibGfx/ICCProfile.cpp +++ b/Userland/Libraries/LibGfx/ICCProfile.cpp @@ -78,7 +78,7 @@ struct ICCHeader { BigEndian profile_device_class; BigEndian data_color_space; - BigEndian pcs; // "Profile Connection Space" + BigEndian profile_connection_space; // "PCS" in the spec. DateTimeNumber profile_creation_time; @@ -126,10 +126,10 @@ ErrorOr parse_device_class(ICCHeader const& header) return Error::from_string_literal("ICC::Profile: Invalid device class"); } -ErrorOr parse_data_color_space(ICCHeader const& header) +ErrorOr parse_color_space(ColorSpace color_space) { - // ICC v4, 7.2.6 Data colour space field - switch (header.data_color_space) { + // ICC v4, Table 19 — Data colour space signatures + switch (color_space) { case ColorSpace::nCIEXYZ: case ColorSpace::CIELAB: case ColorSpace::CIELUV: @@ -155,9 +155,27 @@ ErrorOr parse_data_color_space(ICCHeader const& header) case ColorSpace::ThirteenColor: case ColorSpace::FourteenColor: case ColorSpace::FifteenColor: - return header.data_color_space; + return color_space; } - return Error::from_string_literal("ICC::Profile: Invalid data color space"); + return Error::from_string_literal("ICC::Profile: Invalid color space"); +} + +ErrorOr parse_data_color_space(ICCHeader const& header) +{ + // ICC v4, 7.2.6 Data colour space field + return parse_color_space(header.data_color_space); +} + +ErrorOr parse_connection_space(ICCHeader const& header) +{ + // ICC v4, 7.2.7 PCS field + // and Annex D + auto space = TRY(parse_color_space(header.profile_connection_space)); + + if (header.profile_device_class != DeviceClass::DeviceLink && (space != ColorSpace::PCSXYZ && space != ColorSpace::PCSLAB)) + return Error::from_string_literal("ICC::Profile: Invalid profile connection space: Non-PCS space on non-DeviceLink profile"); + + return space; } ErrorOr parse_rendering_intent(ICCHeader const& header) @@ -212,7 +230,7 @@ StringView device_class_name(DeviceClass device_class) VERIFY_NOT_REACHED(); } -StringView color_space_name(ColorSpace color_space) +StringView data_color_space_name(ColorSpace color_space) { switch (color_space) { case ColorSpace::nCIEXYZ: @@ -269,6 +287,18 @@ StringView color_space_name(ColorSpace color_space) VERIFY_NOT_REACHED(); } +StringView profile_connection_space_name(ColorSpace color_space) +{ + switch (color_space) { + case ColorSpace::PCSXYZ: + return "PCSXYZ"sv; + case ColorSpace::PCSLAB: + return "PCSLAB"sv; + default: + return data_color_space_name(color_space); + } +} + StringView rendering_intent_name(RenderingIntent rendering_intent) { switch (rendering_intent) { @@ -303,6 +333,7 @@ ErrorOr> Profile::try_load_from_externally_owned_memory(R profile->m_version = TRY(parse_version(header)); profile->m_device_class = TRY(parse_device_class(header)); profile->m_data_color_space = TRY(parse_data_color_space(header)); + profile->m_connection_space = TRY(parse_connection_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)); diff --git a/Userland/Libraries/LibGfx/ICCProfile.h b/Userland/Libraries/LibGfx/ICCProfile.h index 11287bd375..aa35616c0c 100644 --- a/Userland/Libraries/LibGfx/ICCProfile.h +++ b/Userland/Libraries/LibGfx/ICCProfile.h @@ -47,8 +47,10 @@ StringView device_class_name(DeviceClass); // ICC v4, 7.2.6 Data colour space field, Table 19 — Data colour space signatures enum class ColorSpace : u32 { - nCIEXYZ = 0x58595A20, // 'XYZ ' - CIELAB = 0x4C616220, // 'Lab ' + nCIEXYZ = 0x58595A20, // 'XYZ ', used in data color spaces. + PCSXYZ = nCIEXYZ, // Used in profile connection space instead. + CIELAB = 0x4C616220, // 'Lab ', used in data color spaces. + PCSLAB = CIELAB, // Used in profile connection space instead. CIELUV = 0x4C757620, // 'Luv ' YCbCr = 0x59436272, // 'YCbr' CIEYxy = 0x59787920, // 'Yxy ' @@ -73,7 +75,8 @@ enum class ColorSpace : u32 { FourteenColor = 0x45434C52, // 'ECLR' FifteenColor = 0x46434C52, // 'FCLR' }; -StringView color_space_name(ColorSpace); +StringView data_color_space_name(ColorSpace); +StringView profile_connection_space_name(ColorSpace); // ICC v4, 7.2.15 Rendering intent field enum class RenderingIntent { @@ -119,6 +122,10 @@ public: Version version() const { return m_version; } DeviceClass device_class() const { return m_device_class; } ColorSpace data_color_space() const { return m_data_color_space; } + + // For non-DeviceLink profiles, always PCSXYZ or PCSLAB. + ColorSpace connection_space() const { return m_connection_space; } + time_t creation_timestamp() const { return m_creation_timestamp; } Flags flags() const { return m_flags; } RenderingIntent rendering_intent() const { return m_rendering_intent; } @@ -127,6 +134,7 @@ private: Version m_version; DeviceClass m_device_class; ColorSpace m_data_color_space; + ColorSpace m_connection_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 9fad397005..863c47022a 100644 --- a/Userland/Utilities/icc.cpp +++ b/Userland/Utilities/icc.cpp @@ -23,7 +23,8 @@ ErrorOr serenity_main(Main::Arguments arguments) outln("version: {}", profile->version()); 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("data color space: {}", Gfx::ICC::data_color_space_name(profile->data_color_space())); + outln("connection space: {}", Gfx::ICC::profile_connection_space_name(profile->connection_space())); outln("creation date and time: {}", Core::DateTime::from_timestamp(profile->creation_timestamp()).to_deprecated_string()); auto flags = profile->flags();