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