160 lines
4.8 KiB
C++
160 lines
4.8 KiB
C++
/*
|
|
* Copyright (c) 2023, Nico Weber <thakis@chromium.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Endian.h>
|
|
#include <LibGfx/ICC/DistinctFourCC.h>
|
|
#include <LibGfx/ICC/Profile.h>
|
|
#include <LibGfx/ICC/TagTypes.h>
|
|
#include <math.h>
|
|
|
|
namespace Gfx::ICC {
|
|
|
|
// ICC V4, 4.2 dateTimeNumber
|
|
// "All the dateTimeNumber values in a profile shall be in Coordinated Universal Time [...]."
|
|
struct DateTimeNumber {
|
|
BigEndian<u16> year;
|
|
BigEndian<u16> month;
|
|
BigEndian<u16> day;
|
|
BigEndian<u16> hours;
|
|
BigEndian<u16> minutes;
|
|
BigEndian<u16> 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<s15Fixed16Number> x;
|
|
BigEndian<s15Fixed16Number> y;
|
|
BigEndian<s15Fixed16Number> 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<u32> profile_size;
|
|
BigEndian<PreferredCMMType> preferred_cmm_type;
|
|
|
|
u8 profile_version_major;
|
|
u8 profile_version_minor_bugfix;
|
|
BigEndian<u16> profile_version_zero;
|
|
|
|
BigEndian<DeviceClass> profile_device_class;
|
|
BigEndian<ColorSpace> data_color_space;
|
|
BigEndian<ColorSpace> profile_connection_space; // "PCS" in the spec.
|
|
|
|
DateTimeNumber profile_creation_time;
|
|
|
|
BigEndian<u32> profile_file_signature;
|
|
BigEndian<PrimaryPlatform> primary_platform;
|
|
|
|
BigEndian<u32> profile_flags;
|
|
BigEndian<DeviceManufacturer> device_manufacturer;
|
|
BigEndian<DeviceModel> device_model;
|
|
BigEndian<u64> device_attributes;
|
|
BigEndian<RenderingIntent> rendering_intent;
|
|
|
|
XYZNumber pcs_illuminant;
|
|
|
|
BigEndian<Creator> profile_creator;
|
|
|
|
u8 profile_id[16];
|
|
u8 reserved[28];
|
|
};
|
|
static_assert(AssertSize<ICCHeader, 128>());
|
|
|
|
// 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<TagSignature> tag_signature;
|
|
BigEndian<u32> offset_to_beginning_of_tag_data_element;
|
|
BigEndian<u32> size_of_tag_data_element;
|
|
};
|
|
static_assert(AssertSize<TagTableEntry, 12>());
|
|
|
|
// 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<s15Fixed16Number> e_parameters[9];
|
|
};
|
|
static_assert(AssertSize<LUTHeader, 40>());
|
|
|
|
// 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<u16> reserved_for_padding;
|
|
BigEndian<u32> offset_to_b_curves;
|
|
BigEndian<u32> offset_to_matrix;
|
|
BigEndian<u32> offset_to_m_curves;
|
|
BigEndian<u32> offset_to_clut;
|
|
BigEndian<u32> offset_to_a_curves;
|
|
};
|
|
static_assert(AssertSize<AdvancedLUTHeader, 24>());
|
|
|
|
// 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<CLUTHeader, 20>());
|
|
|
|
// Table 49 — measurementType structure
|
|
struct MeasurementHeader {
|
|
BigEndian<MeasurementTagData::StandardObserver> standard_observer;
|
|
XYZNumber tristimulus_value_for_measurement_backing;
|
|
BigEndian<MeasurementTagData::MeasurementGeometry> measurement_geometry;
|
|
BigEndian<u16Fixed16Number> measurement_flare;
|
|
BigEndian<MeasurementTagData::StandardIlluminant> standard_illuminant;
|
|
};
|
|
static_assert(AssertSize<MeasurementHeader, 28>());
|
|
|
|
// ICC v4, 10.15 multiLocalizedUnicodeType
|
|
struct MultiLocalizedUnicodeRawRecord {
|
|
BigEndian<u16> language_code;
|
|
BigEndian<u16> country_code;
|
|
BigEndian<u32> string_length_in_bytes;
|
|
BigEndian<u32> string_offset_in_bytes;
|
|
};
|
|
static_assert(AssertSize<MultiLocalizedUnicodeRawRecord, 12>());
|
|
|
|
// 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<MeasurementTagData::StandardIlluminant> illuminant_type;
|
|
};
|
|
static_assert(AssertSize<ViewingConditionsHeader, 28>());
|
|
|
|
}
|