1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 02:07:36 +00:00

LibGfx+icc: Print device attribute flags

These flags are always 0 in practice in all profiles I've seen so far,
but hey, probably nice to dump them anyways.

And hey, it's just 86 lines to print 4 bits.
This commit is contained in:
Nico Weber 2023-01-06 15:06:30 -05:00 committed by Linus Groh
parent 915cc5d4e3
commit d223477bc6
3 changed files with 86 additions and 0 deletions

View file

@ -198,6 +198,17 @@ ErrorOr<time_t> parse_creation_date_time(ICCHeader const& header)
return parse_date_time_number(header.profile_creation_time);
}
ErrorOr<DeviceAttributes> parse_device_attributes(ICCHeader const& header)
{
// ICC v4, 7.2.14 Device attributes field
// "4 to 31": "Reserved (set to binary zero)"
if (header.device_attributes & 0xffff'fff0)
return Error::from_string_literal("ICC::Profile: Device attributes reserved bits not set to 0");
return DeviceAttributes { header.device_attributes };
}
ErrorOr<void> parse_file_signature(ICCHeader const& header)
{
// ICC v4, 7.2.9 Profile file signature field
@ -383,6 +394,12 @@ Flags::Flags(u32 bits)
{
}
DeviceAttributes::DeviceAttributes() = default;
DeviceAttributes::DeviceAttributes(u64 bits)
: m_bits(bits)
{
}
ErrorOr<NonnullRefPtr<Profile>> Profile::try_load_from_externally_owned_memory(ReadonlyBytes bytes)
{
auto profile = adopt_ref(*new Profile());
@ -399,6 +416,7 @@ ErrorOr<NonnullRefPtr<Profile>> Profile::try_load_from_externally_owned_memory(R
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_device_attributes = TRY(parse_device_attributes(header));
profile->m_rendering_intent = TRY(parse_rendering_intent(header));
profile->m_pcs_illuminant = TRY(parse_pcs_illuminant(header));
profile->m_id = TRY(parse_profile_id(header, bytes));

View file

@ -116,6 +116,61 @@ private:
u32 m_bits = 0;
};
// ICC v4, 7.2.14 Device attributes field
class DeviceAttributes {
public:
DeviceAttributes();
// "The device attributes field shall contain flags used to identify attributes
// unique to the particular device setup for which the profile is applicable."
DeviceAttributes(u64);
u64 bits() const { return m_bits; }
// "The least-significant 32 bits of this 64-bit value are defined by the ICC. "
u32 icc_bits() const { return bits() & 0xffff'ffff; }
// "Notice that bits 0, 1, 2, and 3 describe the media, not the device."
// "0": "Reflective (0) or transparency (1)"
enum class MediaReflectivity {
Reflective,
Transparent,
};
MediaReflectivity media_reflectivity() const { return MediaReflectivity(icc_bits() & 1); }
// "1": "Glossy (0) or matte (1)"
enum class MediaGlossiness {
Glossy,
Matte,
};
MediaGlossiness media_glossiness() const { return MediaGlossiness((icc_bits() >> 1) & 1); }
// "2": "Media polarity, positive (0) or negative (1)"
enum class MediaPolarity {
Positive,
Negative,
};
MediaPolarity media_polarity() const { return MediaPolarity((icc_bits() >> 2) & 1); }
// "3": "Colour media (0), black & white media (1)"
enum class MediaColor {
Colored,
BlackAndWhite,
};
MediaColor media_color() const { return MediaColor((icc_bits() >> 3) & 1); }
// "4 to 31": Reserved (set to binary zero)"
// "32 to 63": "Use not defined by ICC (vendor specific"
u32 vendor_bits() const { return bits() >> 32; }
static constexpr u64 KnownBitsMask = 0xf;
private:
u64 m_bits = 0;
};
struct XYZ {
double x { 0 };
double y { 0 };
@ -135,6 +190,7 @@ public:
time_t creation_timestamp() const { return m_creation_timestamp; }
Flags flags() const { return m_flags; }
DeviceAttributes device_attributes() const { return m_device_attributes; }
RenderingIntent rendering_intent() const { return m_rendering_intent; }
XYZ const& pcs_illuminant() const { return m_pcs_illuminant; }
Optional<Crypto::Hash::MD5::DigestType> const& id() const { return m_id; }
@ -148,6 +204,7 @@ private:
ColorSpace m_connection_space;
time_t m_creation_timestamp;
Flags m_flags;
DeviceAttributes m_device_attributes;
RenderingIntent m_rendering_intent;
XYZ m_pcs_illuminant;
Optional<Crypto::Hash::MD5::DigestType> m_id;

View file

@ -36,6 +36,17 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
if (auto color_management_module_bits = flags.color_management_module_bits())
outln(" CMM bits: 0x{:04x}", color_management_module_bits);
auto device_attributes = profile->device_attributes();
outln("device attributes: 0x{:016x}", device_attributes.bits());
outln(" media is {}, {}, {}, {}",
device_attributes.media_reflectivity() == Gfx::ICC::DeviceAttributes::MediaReflectivity::Reflective ? "reflective" : "transparent",
device_attributes.media_glossiness() == Gfx::ICC::DeviceAttributes::MediaGlossiness::Glossy ? "glossy" : "matte",
device_attributes.media_polarity() == Gfx::ICC::DeviceAttributes::MediaPolarity::Positive ? "of positive polarity" : "of negative polarity",
device_attributes.media_color() == Gfx::ICC::DeviceAttributes::MediaColor::Colored ? "colored" : "black and white");
VERIFY((flags.icc_bits() & ~Gfx::ICC::DeviceAttributes::KnownBitsMask) == 0);
if (auto vendor_bits = device_attributes.vendor_bits())
outln(" vendor bits: 0x{:08x}", vendor_bits);
outln("rendering intent: {}", Gfx::ICC::rendering_intent_name(profile->rendering_intent()));
outln("pcs illuminant: {}", profile->pcs_illuminant());