aboutsummaryrefslogtreecommitdiffstats
path: root/redshift/colour.c
blob: 4d85cb57a30b5157383e5cb5a5a5d950bd2e5365 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*-
 * redshift-ng - Automatically adjust display colour temperature according the Sun
 * 
 * Copyright (c) 2009-2018        Jon Lund Steffensen <jonlst@gmail.com>
 * Copyright (c) 2014-2016, 2025  Mattias Andrée <m@maandree.se>
 * 
 * redshift-ng is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * redshift-ng is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with redshift-ng.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "common.h"


void
interpolate_colour_settings(const struct colour_setting *a, const struct colour_setting *b,
                            double t, struct colour_setting *result)
{
	int i;
	t = CLAMP(0.0, t, 1.0);
	result->temperature = (1.0 - t) * a->temperature + t * b->temperature;
	result->brightness  = (1.0 - t) * a->brightness  + t * b->brightness;
	for (i = 0; i < 3; i++)
		result->gamma[i] = (1.0 - t) * a->gamma[i] + t * b->gamma[i];
}


int
colour_setting_diff_is_major(const struct colour_setting *a, const struct colour_setting *b)
{
	return MAX(a->temperature, b->temperature) - MIN(a->temperature, b->temperature) > 25UL ||
	       fabs(a->brightness - b->brightness) > 0.1 ||
	       fabs(a->gamma[0] - b->gamma[0]) > 0.1 ||
	       fabs(a->gamma[1] - b->gamma[1]) > 0.1 ||
	       fabs(a->gamma[2] - b->gamma[2]) > 0.1;
}


#define X(SUFFIX, RAMPS, TYPE, MAX, DEPTH)\
	/**
	 * Fill a gamma ramp
	 * 
	 * @param  ramp        The gamma ramp
	 * @param  saved       Saved gamma ramp with calibrations to preserver, or `NULL`
	 * @param  size        The gamma ramp size (number of stops)
	 * @param  brightness  The brightness (between 0 and 1) of the channel, which is
	 *                     the overall applied brightness multiplied but the effect
	 *                     on the channel from the colour temperature
	 * @param  gamma       The gamma to apply to the channel
	 */\
	static void\
	fill_ramp_##SUFFIX(TYPE *ramp, const TYPE *saved, size_t size, double brightness, double gamma)\
	{\
		size_t i;\
		double v;\
		brightness /= (size - 1U);\
		if (exact_eq(gamma, 1.0)) {\
			brightness *= (MAX);\
			for (i = 0; i < size; i++)\
				ramp[i] = (TYPE)(i * brightness);\
		} else {\
			gamma = 1.0 / gamma;\
			for (i = 0; i < size; i++) {\
				v = pow(i * brightness, gamma) * (MAX);\
				ramp[i] = (TYPE)v;\
			}\
		}\
		if (saved) {\
			for (i = 0; i < size; i++) {\
				v = (double)ramp[i] / (MAX) * (size - 1U);\
				ramp[i] = saved[(size_t)v];\
			}\
		}\
	}\
	\
	void\
	fill_ramps_##SUFFIX(TYPE *gamma_r, TYPE *gamma_g, TYPE *gamma_b,\
	                    const TYPE *saved_r, const TYPE *saved_g, const TYPE *saved_b,\
	                    size_t size_r, size_t size_g, size_t size_b,\
	                    const struct colour_setting *setting)\
	{\
		double r = 1, g = 1, b = 1;\
		libred_get_colour(setting->temperature, &r, &g, &b);\
		fill_ramp_##SUFFIX(gamma_r, saved_r, size_r, setting->brightness * r, setting->gamma[0]);\
		fill_ramp_##SUFFIX(gamma_g, saved_g, size_g, setting->brightness * g, setting->gamma[1]);\
		fill_ramp_##SUFFIX(gamma_b, saved_b, size_b, setting->brightness * b, setting->gamma[2]);\
	}

LIST_RAMPS_STOP_VALUE_TYPES(X,)