render/color: introduce wlr_color_transform_matrix

This is useful to perform color space conversions.
This commit is contained in:
Simon Ser 2025-10-28 18:37:37 +01:00
parent 17f3f28865
commit 2995f31102
3 changed files with 31 additions and 1 deletions

View file

@ -9,6 +9,7 @@ enum wlr_color_transform_type {
COLOR_TRANSFORM_INVERSE_EOTF,
COLOR_TRANSFORM_LCMS2,
COLOR_TRANSFORM_LUT_3X1D,
COLOR_TRANSFORM_MATRIX,
COLOR_TRANSFORM_PIPELINE,
};
@ -40,6 +41,12 @@ struct wlr_color_transform_lut_3x1d {
size_t dim;
};
struct wlr_color_transform_matrix {
struct wlr_color_transform base;
float matrix[9];
};
struct wlr_color_transform_pipeline {
struct wlr_color_transform base;

View file

@ -141,6 +141,12 @@ struct wlr_color_transform *wlr_color_transform_init_linear_to_inverse_eotf(
struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim,
const uint16_t *r, const uint16_t *g, const uint16_t *b);
/**
* Initialize a color transformation to apply a 3×3 matrix. Returns NULL on
* failure.
*/
struct wlr_color_transform *wlr_color_transform_init_matrix(const float matrix[static 9]);
/**
* Initialize a color transformation to apply a sequence of color transforms
* one after another.

View file

@ -62,6 +62,16 @@ struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim,
return &tx->base;
}
struct wlr_color_transform *wlr_color_transform_init_matrix(const float matrix[static 9]) {
struct wlr_color_transform_matrix *tx = calloc(1, sizeof(*tx));
if (!tx) {
return NULL;
}
wlr_color_transform_init(&tx->base, COLOR_TRANSFORM_MATRIX);
memcpy(tx->matrix, matrix, sizeof(tx->matrix));
return &tx->base;
}
struct wlr_color_transform *wlr_color_transform_init_pipeline(
struct wlr_color_transform **transforms, size_t len) {
assert(len > 0);
@ -92,6 +102,7 @@ struct wlr_color_transform *wlr_color_transform_init_pipeline(
static void color_transform_destroy(struct wlr_color_transform *tr) {
switch (tr->type) {
case COLOR_TRANSFORM_INVERSE_EOTF:
case COLOR_TRANSFORM_MATRIX:
break;
case COLOR_TRANSFORM_LCMS2:
color_transform_lcms2_finish(color_transform_lcms2_from_base(tr));
@ -226,6 +237,8 @@ static void color_transform_lut_3x1d_eval(struct wlr_color_transform_lut_3x1d *t
}
}
static void multiply_matrix_vector(float out[static 3], float m[static 9], const float v[static 3]);
void wlr_color_transform_eval(struct wlr_color_transform *tr,
float out[static 3], const float in[static 3]) {
switch (tr->type) {
@ -238,6 +251,10 @@ void wlr_color_transform_eval(struct wlr_color_transform *tr,
case COLOR_TRANSFORM_LUT_3X1D:
color_transform_lut_3x1d_eval(color_transform_lut_3x1d_from_base(tr), out, in);
break;
case COLOR_TRANSFORM_MATRIX:;
struct wlr_color_transform_matrix *matrix = wl_container_of(tr, matrix, base);
multiply_matrix_vector(out, matrix->matrix, in);
break;
case COLOR_TRANSFORM_PIPELINE:;
struct wlr_color_transform_pipeline *pipeline =
wl_container_of(tr, pipeline, base);
@ -264,7 +281,7 @@ void wlr_color_primaries_from_named(struct wlr_color_primaries *out,
abort();
}
static void multiply_matrix_vector(float out[static 3], float m[static 9], float v[static 3]) {
static void multiply_matrix_vector(float out[static 3], float m[static 9], const float v[static 3]) {
float result[3] = {
m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
m[3] * v[0] + m[4] * v[1] + m[5] * v[2],