diff --git a/Userland/Libraries/LibGfx/ICC/Profile.cpp b/Userland/Libraries/LibGfx/ICC/Profile.cpp index 102ce31e802..56e05baa1b3 100644 --- a/Userland/Libraries/LibGfx/ICC/Profile.cpp +++ b/Userland/Libraries/LibGfx/ICC/Profile.cpp @@ -572,6 +572,8 @@ ErrorOr> Profile::read_tag(ReadonlyBytes bytes, u32 offse auto type = tag_type(tag_bytes); switch (type) { + case CicpTagData::Type: + return CicpTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element); case CurveTagData::Type: return CurveTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element); case Lut16TagData::Type: diff --git a/Userland/Libraries/LibGfx/ICC/TagTypes.cpp b/Userland/Libraries/LibGfx/ICC/TagTypes.cpp index d29321a7eaf..57b1833d8f4 100644 --- a/Userland/Libraries/LibGfx/ICC/TagTypes.cpp +++ b/Userland/Libraries/LibGfx/ICC/TagTypes.cpp @@ -57,6 +57,23 @@ TagTypeSignature tag_type(ReadonlyBytes tag_bytes) return *bit_cast const*>(tag_bytes.data()); } +ErrorOr> CicpTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size) +{ + // ICC v4, 10.3 cicpType + VERIFY(tag_type(bytes) == Type); + TRY(check_reserved(bytes)); + + if (bytes.size() < 2 * sizeof(u32) + 4 * sizeof(u8)) + return Error::from_string_literal("ICC::Profile: cicpType has not enough data"); + + u8 color_primaries = bytes[8]; + u8 transfer_characteristics = bytes[9]; + u8 matrix_coefficients = bytes[10]; + u8 video_full_range_flag = bytes[11]; + + return adopt_ref(*new CicpTagData(offset, size, color_primaries, transfer_characteristics, matrix_coefficients, video_full_range_flag)); +} + ErrorOr> CurveTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size) { // ICC v4, 10.6 curveType diff --git a/Userland/Libraries/LibGfx/ICC/TagTypes.h b/Userland/Libraries/LibGfx/ICC/TagTypes.h index 9c3b3969a49..fc4c1b0060e 100644 --- a/Userland/Libraries/LibGfx/ICC/TagTypes.h +++ b/Userland/Libraries/LibGfx/ICC/TagTypes.h @@ -58,6 +58,39 @@ public: } }; +// ICC v4, 10.3 cicpType +// "The cicpType specifies Coding-independent code points for video signal type identification." +// See presentations at https://www.color.org/events/HDR_experts.xalter for background. +class CicpTagData : public TagData { +public: + static constexpr TagTypeSignature Type { 0x63696370 }; // 'cicp' + + static ErrorOr> from_bytes(ReadonlyBytes, u32 offset, u32 size); + + CicpTagData(u32 offset, u32 size, u8 color_primaries, u8 transfer_characteristics, u8 matrix_coefficients, u8 video_full_range_flag) + : TagData(offset, size, Type) + , m_color_primaries(color_primaries) + , m_transfer_characteristics(transfer_characteristics) + , m_matrix_coefficients(matrix_coefficients) + , m_video_full_range_flag(video_full_range_flag) + { + } + + // "The fields ColourPrimaries, TransferCharacteristics, MatrixCoefficients, and VideoFullRangeFlag shall be + // encoded as specified in Recommendation ITU-T H.273. Recommendation ITU-T H.273 (ISO/IEC 23091-2) + // provides detailed descriptions of the code values and their interpretation." + u8 color_primaries() const { return m_color_primaries; } + u8 transfer_characteristics() const { return m_transfer_characteristics; } + u8 matrix_coefficients() const { return m_matrix_coefficients; } + u8 video_full_range_flag() const { return m_video_full_range_flag; } + +private: + u8 m_color_primaries; + u8 m_transfer_characteristics; + u8 m_matrix_coefficients; + u8 m_video_full_range_flag; +}; + // ICC v4, 10.6 curveType class CurveTagData : public TagData { public: diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index d05c679111c..6316ffb0aa1 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -94,7 +94,7 @@ target_link_libraries(grep PRIVATE LibRegex) target_link_libraries(gunzip PRIVATE LibCompress) target_link_libraries(gzip PRIVATE LibCompress) target_link_libraries(headless-browser PRIVATE LibCrypto LibGemini LibGfx LibHTTP LibTLS LibWeb LibWebSocket LibIPC LibJS) -target_link_libraries(icc PRIVATE LibGfx) +target_link_libraries(icc PRIVATE LibGfx LibVideo) target_link_libraries(image2bin PRIVATE LibGfx) target_link_libraries(jail-attach PRIVATE LibCore LibMain) target_link_libraries(jail-create PRIVATE LibCore LibMain) diff --git a/Userland/Utilities/icc.cpp b/Userland/Utilities/icc.cpp index e0c43c68b54..f8e6ff6284e 100644 --- a/Userland/Utilities/icc.cpp +++ b/Userland/Utilities/icc.cpp @@ -12,6 +12,7 @@ #include #include #include +#include template static ErrorOr hyperlink(URL const& target, T const& label) @@ -125,7 +126,16 @@ ErrorOr serenity_main(Main::Arguments arguments) } tag_data_to_first_signature.set(tag_data, tag_signature); - if (tag_data->type() == Gfx::ICC::CurveTagData::Type) { + if (tag_data->type() == Gfx::ICC::CicpTagData::Type) { + auto& cicp = static_cast(*tag_data); + outln(" color primaries: {} - {}", cicp.color_primaries(), + Video::color_primaries_to_string((Video::ColorPrimaries)cicp.color_primaries())); + outln(" transfer characteristics: {} - {}", cicp.transfer_characteristics(), + Video::transfer_characteristics_to_string((Video::TransferCharacteristics)cicp.transfer_characteristics())); + outln(" matrix coefficients: {} - {}", cicp.matrix_coefficients(), + Video::matrix_coefficients_to_string((Video::MatrixCoefficients)cicp.matrix_coefficients())); + outln(" video full range flag: {}", cicp.video_full_range_flag()); + } else if (tag_data->type() == Gfx::ICC::CurveTagData::Type) { auto& curve = static_cast(*tag_data); if (curve.values().is_empty()) { outln(" identity curve");