Refactor RGB & XYZ colors into structs
parent
afc09a90c6
commit
20d37fb751
47
color_math.c
47
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
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
color_math.h
10
color_math.h
|
@ -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
14
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,
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue