From 3b3fa61c31ec6ac8851cb0d7430335f64b295e09 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 2 May 2025 15:50:40 +0300 Subject: [PATCH] color: add Bradford matrix computation This function is required for media-relative rendering intents. Signed-off-by: Pekka Paalanen --- include/libweston/colorimetry.h | 3 +++ libweston/color.c | 32 ++++++++++++++++++++++++++++++++ tests/color-math-test.c | 18 ++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/include/libweston/colorimetry.h b/include/libweston/colorimetry.h index fde50d3ae..ebe826e0f 100644 --- a/include/libweston/colorimetry.h +++ b/include/libweston/colorimetry.h @@ -152,6 +152,9 @@ weston_normalized_primary_matrix_init(struct weston_mat3f *npm, const struct weston_color_gamut *gamut, enum weston_npm_direction dir); +struct weston_mat3f +weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to); + /** Color primaries known by libweston */ enum weston_color_primaries { WESTON_PRIMARIES_CICP_SRGB = 0, diff --git a/libweston/color.c b/libweston/color.c index d3e45bb22..7588f43bf 100644 --- a/libweston/color.c +++ b/libweston/color.c @@ -1038,3 +1038,35 @@ weston_normalized_primary_matrix_init(struct weston_mat3f *npm, return true; } + +/** Compute linearized Bradford transformation + * + * \param from Source adapted white point. + * \param to Destination adapted white point. + * \return Full adaptation matrix. + * + * Based on ICC.1:2022 (ICC v4.4), annex E. + */ +WL_EXPORT struct weston_mat3f +weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to) +{ + static const struct weston_mat3f bradford = WESTON_MAT3F( + 0.8951, 0.2664, -0.1614, + -0.7502, 1.7135, 0.0367, + 0.0389, -0.0685, 1.0296 + ); + struct weston_mat3f inv; + struct weston_vec3f from_cr; + struct weston_vec3f to_cr; + struct weston_vec3f r; + struct weston_mat3f tmp; + + weston_m3f_invert(&inv, bradford); + from_cr = weston_m3f_mul_v3f(bradford, CIExy_to_XYZ(from)); + to_cr = weston_m3f_mul_v3f(bradford, CIExy_to_XYZ(to)); + r = WESTON_VEC3F(to_cr.x / from_cr.x, + to_cr.y / from_cr.y, + to_cr.z / from_cr.z); + tmp = weston_m3f_mul_m3f(weston_m3f_diag(r), bradford); + return weston_m3f_mul_m3f(inv, tmp); +} diff --git a/tests/color-math-test.c b/tests/color-math-test.c index ada8775b9..b5bbd65a7 100644 --- a/tests/color-math-test.c +++ b/tests/color-math-test.c @@ -356,3 +356,21 @@ TEST_P(npm, npm_test_cases) return RESULT_OK; } + +/* https://www.color.org/chadtag.xalter */ +TEST(bradform_adaptation_D65_D50) +{ + const struct weston_CIExy D65 = { 0.3127, 0.3290 }; + const struct weston_CIExy D50 = { 0.3457, 0.3585 }; + const struct weston_mat3f ref = WESTON_MAT3F( + 1.04790738171017, 0.0229333845542104, -0.0502016347980104, + 0.0296059594177168, 0.990456039910785, -0.01707552919587, + -0.00924679432678241, 0.0150626801401488, 0.751791232609078 + ); + struct weston_mat3f M; + + M = weston_bradford_adaptation(D65, D50); + test_assert_f32_ge(diff_precision(M, ref), 13); + + return RESULT_OK; +}