Refactor RGB & XYZ colors into structs

master
Artur Sinila 2022-01-24 20:19:09 +02:00 committed by Kenny Levinsen
parent afc09a90c6
commit 20d37fb751
3 changed files with 40 additions and 33 deletions

View File

@ -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 // 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); return (struct rgb) {
*g = srgb_gamma(clamp(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), 2.2); .r = srgb_gamma(clamp(3.2404542 * xyz->x - 1.5371385 * xyz->y - 0.4985314 * xyz->z), 2.2),
*b = srgb_gamma(clamp(0.0556434 * x - 0.2040259 * y + 1.0572252 * 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) { static void srgb_normalize(struct rgb *rgb) {
double maxw = fmaxl(*r, fmaxl(*g, *b)); double maxw = fmax(rgb->r, fmax(rgb->g, rgb->b));
*r /= maxw; rgb->r /= maxw;
*g /= maxw; rgb->g /= maxw;
*b /= maxw; rgb->b /= maxw;
} }
void calc_whitepoint(int temp, double *rw, double *gw, double *bw) { struct rgb calc_whitepoint(int temp) {
if (temp == 6500) { if (temp == 6500) {
*rw = *gw = *bw = 1.0; return (struct rgb) {.r = 1.0, .g = 1.0, .b = 1.0};
return;
} }
double x = 1.0, y = 1.0; struct xyz wp;
if (temp >= 25000) { if (temp >= 25000) {
illuminant_d(25000, &x, &y); illuminant_d(25000, &wp.x, &wp.y);
} else if (temp >= 4000) { } else if (temp >= 4000) {
illuminant_d(temp, &x, &y); illuminant_d(temp, &wp.x, &wp.y);
} else if (temp >= 2500) { } else if (temp >= 2500) {
double x1, y1, x2, y2; double x1, y1, x2, y2;
illuminant_d(temp, &x1, &y1); 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 factor = (4000 - temp) / 1500;
double sinefactor = (cos(M_PI*factor) + 1.0) / 2.0; double sinefactor = (cos(M_PI*factor) + 1.0) / 2.0;
x = x1 * sinefactor + x2 * (1.0 - sinefactor); wp.x = x1 * sinefactor + x2 * (1.0 - sinefactor);
y = y1 * sinefactor + y2 * (1.0 - sinefactor); wp.y = y1 * sinefactor + y2 * (1.0 - sinefactor);
} else if (temp >= 1667) {
planckian_locus(temp, &x, &y);
} else { } else {
planckian_locus(1667, &x, &y); 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); struct rgb wp_rgb = xyz_to_srgb(&wp);
srgb_normalize(rw, gw, bw); srgb_normalize(&wp_rgb);
return wp_rgb;
} }

View File

@ -22,7 +22,15 @@ struct sun {
time_t dusk; 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); 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 #endif

14
main.c
View File

@ -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, static void set_temperature(struct output *output, const struct rgb *wp, double gamma) {
double gw, double bw, double gamma) {
if (output->gamma_control == NULL || output->table_fd == -1) { if (output->gamma_control == NULL || output->table_fd == -1) {
return; 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); lseek(output->table_fd, 0, SEEK_SET);
zwlr_gamma_control_v1_set_gamma(output->gamma_control, zwlr_gamma_control_v1_set_gamma(output->gamma_control,
output->table_fd); output->table_fd);
} }
static void set_temperature_all_outputs(struct wl_list *outputs, static void set_temperature_all_outputs(struct wl_list *outputs,
struct config *cfg, int temp, double gamma) { const struct config *cfg, int temp, double gamma) {
double rw, gw, bw; struct rgb wp = calc_whitepoint(temp);
calc_whitepoint(temp, &rw, &gw, &bw);
// If outputs specified by user, then set temperature only for them. // If outputs specified by user, then set temperature only for them.
// Otherwise set temperature for all outputs. // Otherwise set temperature for all outputs.
@ -600,7 +598,7 @@ static void set_temperature_all_outputs(struct wl_list *outputs,
fprintf(stderr, fprintf(stderr,
"setting temperature on '%s' to %d K\n", "setting temperature on '%s' to %d K\n",
output->name, temp); output->name, temp);
set_temperature(output, rw, gw, bw, gamma); set_temperature(output, &wp, gamma);
output_exists = true; output_exists = true;
break; break;
} }
@ -616,7 +614,7 @@ static void set_temperature_all_outputs(struct wl_list *outputs,
fprintf(stderr, fprintf(stderr,
"setting temperature on output '%d' to %d K\n", "setting temperature on output '%d' to %d K\n",
output->id, temp); output->id, temp);
set_temperature(output, rw, gw, bw, gamma); set_temperature(output, &wp, gamma);
} }
} }
} }