/* * Copyright (c) 2023, Nico Weber * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace Gfx::ICC { // ICC V4, 4.2 dateTimeNumber // "All the dateTimeNumber values in a profile shall be in Coordinated Universal Time [...]." struct DateTimeNumber { BigEndian year; BigEndian month; BigEndian day; BigEndian hours; BigEndian minutes; BigEndian seconds; }; // ICC V4, 4.6 s15Fixed16Number using s15Fixed16Number = i32; // ICC V4, 4.7 u16Fixed16Number using u16Fixed16Number = u32; // ICC V4, 4.14 XYZNumber struct XYZNumber { BigEndian x; BigEndian y; BigEndian z; XYZNumber() = default; XYZNumber(XYZ const& xyz) : x(round(xyz.x * 0x1'0000)) , y(round(xyz.y * 0x1'0000)) , z(round(xyz.z * 0x1'0000)) { } operator XYZ() const { return XYZ { x / (double)0x1'0000, y / (double)0x1'0000, z / (double)0x1'0000 }; } }; // ICC V4, 7.2 Profile header struct ICCHeader { BigEndian profile_size; BigEndian preferred_cmm_type; u8 profile_version_major; u8 profile_version_minor_bugfix; BigEndian profile_version_zero; BigEndian profile_device_class; BigEndian data_color_space; BigEndian profile_connection_space; // "PCS" in the spec. DateTimeNumber profile_creation_time; BigEndian profile_file_signature; BigEndian primary_platform; BigEndian profile_flags; BigEndian device_manufacturer; BigEndian device_model; BigEndian device_attributes; BigEndian rendering_intent; XYZNumber pcs_illuminant; BigEndian profile_creator; u8 profile_id[16]; u8 reserved[28]; }; static_assert(AssertSize()); // ICC v4, 7.2.9 Profile file signature field // "The profile file signature field shall contain the value “acsp” (61637370h) as a profile file signature." constexpr u32 ProfileFileSignature = 0x61637370; // ICC V4, 7.3 Tag table, Table 24 - Tag table structure struct TagTableEntry { BigEndian tag_signature; BigEndian offset_to_beginning_of_tag_data_element; BigEndian size_of_tag_data_element; }; static_assert(AssertSize()); // Common bits of ICC v4, Table 40 — lut16Type encoding and Table 44 — lut8Type encoding struct LUTHeader { u8 number_of_input_channels; u8 number_of_output_channels; u8 number_of_clut_grid_points; u8 reserved_for_padding; BigEndian e_parameters[9]; }; static_assert(AssertSize()); // Common bits of ICC v4, Table 45 — lutAToBType encoding and Table 47 — lutBToAType encoding struct AdvancedLUTHeader { u8 number_of_input_channels; u8 number_of_output_channels; BigEndian reserved_for_padding; BigEndian offset_to_b_curves; BigEndian offset_to_matrix; BigEndian offset_to_m_curves; BigEndian offset_to_clut; BigEndian offset_to_a_curves; }; static_assert(AssertSize()); // ICC v4, Table 46 — lutAToBType CLUT encoding // ICC v4, Table 48 — lutBToAType CLUT encoding // (They're identical.) struct CLUTHeader { u8 number_of_grid_points_in_dimension[16]; u8 precision_of_data_elements; // 1 for u8 entries, 2 for u16 entries. u8 reserved_for_padding[3]; }; static_assert(AssertSize()); // Table 49 — measurementType structure struct MeasurementHeader { BigEndian standard_observer; XYZNumber tristimulus_value_for_measurement_backing; BigEndian measurement_geometry; BigEndian measurement_flare; BigEndian standard_illuminant; }; static_assert(AssertSize()); // ICC v4, 10.15 multiLocalizedUnicodeType struct MultiLocalizedUnicodeRawRecord { BigEndian language_code; BigEndian country_code; BigEndian string_length_in_bytes; BigEndian string_offset_in_bytes; }; static_assert(AssertSize()); // Table 66 — namedColor2Type encoding struct NamedColorHeader { BigEndian vendor_specific_flag; BigEndian count_of_named_colors; BigEndian number_of_device_coordinates_of_each_named_color; u8 prefix_for_each_color_name[32]; // null-terminated u8 suffix_for_each_color_name[32]; // null-terminated }; static_assert(AssertSize()); // Table 84 — viewingConditionsType encoding struct ViewingConditionsHeader { XYZNumber unnormalized_ciexyz_values_for_illuminant; // "(in which Y is in cd/m2)" XYZNumber unnormalized_ciexyz_values_for_surround; // "(in which Y is in cd/m2)" BigEndian illuminant_type; }; static_assert(AssertSize()); }