From 20d37fb75197de5248528c5164f8cc86f7161b22 Mon Sep 17 00:00:00 2001 From: Artur Sinila Date: Mon, 24 Jan 2022 20:19:09 +0200 Subject: [PATCH] Refactor RGB & XYZ colors into structs --- color_math.c | 49 +++++++++++++++++++++++++------------------------ color_math.h | 10 +++++++++- main.c | 14 ++++++-------- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/color_math.c b/color_math.c index b850b96..ace8b17 100644 --- a/color_math.c +++ b/color_math.c @@ -159,31 +159,32 @@ static double clamp(double value) { } } -static void xyz_to_srgb(double x, double y, double z, double *r, double *g, double *b) { +static struct rgb xyz_to_srgb(const struct xyz *xyz) { // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html - *r = srgb_gamma(clamp(3.2404542 * x - 1.5371385 * y - 0.4985314 * z), 2.2); - *g = srgb_gamma(clamp(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), 2.2); - *b = srgb_gamma(clamp(0.0556434 * x - 0.2040259 * y + 1.0572252 * z), 2.2); + return (struct rgb) { + .r = srgb_gamma(clamp(3.2404542 * xyz->x - 1.5371385 * xyz->y - 0.4985314 * xyz->z), 2.2), + .g = srgb_gamma(clamp(-0.9692660 * xyz->x + 1.8760108 * xyz->y + 0.0415560 * xyz->z), 2.2), + .b = srgb_gamma(clamp(0.0556434 * xyz->x - 0.2040259 * xyz->y + 1.0572252 * xyz->z), 2.2) + }; } -static void srgb_normalize(double *r, double *g, double *b) { - double maxw = fmaxl(*r, fmaxl(*g, *b)); - *r /= maxw; - *g /= maxw; - *b /= maxw; +static void srgb_normalize(struct rgb *rgb) { + double maxw = fmax(rgb->r, fmax(rgb->g, rgb->b)); + rgb->r /= maxw; + rgb->g /= maxw; + rgb->b /= maxw; } -void calc_whitepoint(int temp, double *rw, double *gw, double *bw) { +struct rgb calc_whitepoint(int temp) { if (temp == 6500) { - *rw = *gw = *bw = 1.0; - return; + return (struct rgb) {.r = 1.0, .g = 1.0, .b = 1.0}; } - double x = 1.0, y = 1.0; + struct xyz wp; if (temp >= 25000) { - illuminant_d(25000, &x, &y); + illuminant_d(25000, &wp.x, &wp.y); } else if (temp >= 4000) { - illuminant_d(temp, &x, &y); + illuminant_d(temp, &wp.x, &wp.y); } else if (temp >= 2500) { double x1, y1, x2, y2; illuminant_d(temp, &x1, &y1); @@ -191,16 +192,16 @@ void calc_whitepoint(int temp, double *rw, double *gw, double *bw) { double factor = (4000 - temp) / 1500; double sinefactor = (cos(M_PI*factor) + 1.0) / 2.0; - x = x1 * sinefactor + x2 * (1.0 - sinefactor); - y = y1 * sinefactor + y2 * (1.0 - sinefactor); - } else if (temp >= 1667) { - planckian_locus(temp, &x, &y); - } else { - planckian_locus(1667, &x, &y); + wp.x = x1 * sinefactor + x2 * (1.0 - sinefactor); + wp.y = y1 * sinefactor + y2 * (1.0 - sinefactor); + } else { + planckian_locus(temp >= 1667 ? temp : 1667, &wp.x, &wp.y); } - double z = 1.0 - x - y; + wp.z = 1.0 - wp.x - wp.y; - xyz_to_srgb(x, y, z, rw, gw, bw); - srgb_normalize(rw, gw, bw); + struct rgb wp_rgb = xyz_to_srgb(&wp); + srgb_normalize(&wp_rgb); + + return wp_rgb; } diff --git a/color_math.h b/color_math.h index 629d2b7..b49d119 100644 --- a/color_math.h +++ b/color_math.h @@ -22,7 +22,15 @@ struct sun { time_t dusk; }; +struct rgb { + double r, g, b; +}; + +struct xyz { + double x, y, z; +}; + enum sun_condition calc_sun(struct tm *tm, double latitude, struct sun *sun); -void calc_whitepoint(int temp, double *rw, double *gw, double *bw); +struct rgb calc_whitepoint(int temp); #endif diff --git a/main.c b/main.c index 6378a3c..a2937cd 100644 --- a/main.c +++ b/main.c @@ -573,21 +573,19 @@ static void fill_gamma_table(uint16_t *table, uint32_t ramp_size, double rw, } } -static void set_temperature(struct output *output, double rw, - double gw, double bw, double gamma) { +static void set_temperature(struct output *output, const struct rgb *wp, double gamma) { if (output->gamma_control == NULL || output->table_fd == -1) { return; } - fill_gamma_table(output->table, output->ramp_size, rw, gw, bw, gamma); + fill_gamma_table(output->table, output->ramp_size, wp->r, wp->g, wp->b, gamma); lseek(output->table_fd, 0, SEEK_SET); zwlr_gamma_control_v1_set_gamma(output->gamma_control, output->table_fd); } static void set_temperature_all_outputs(struct wl_list *outputs, - struct config *cfg, int temp, double gamma) { - double rw, gw, bw; - calc_whitepoint(temp, &rw, &gw, &bw); + const struct config *cfg, int temp, double gamma) { + struct rgb wp = calc_whitepoint(temp); // If outputs specified by user, then set temperature only for them. // Otherwise set temperature for all outputs. @@ -600,7 +598,7 @@ static void set_temperature_all_outputs(struct wl_list *outputs, fprintf(stderr, "setting temperature on '%s' to %d K\n", output->name, temp); - set_temperature(output, rw, gw, bw, gamma); + set_temperature(output, &wp, gamma); output_exists = true; break; } @@ -616,7 +614,7 @@ static void set_temperature_all_outputs(struct wl_list *outputs, fprintf(stderr, "setting temperature on output '%d' to %d K\n", output->id, temp); - set_temperature(output, rw, gw, bw, gamma); + set_temperature(output, &wp, gamma); } } }