Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f2aa7c8

Browse files
authoredDec 16, 2022
[xsct 1.9] Fix issue #32 by adding linear brightness parameter (PR #33)
Add second argument: Linear brightness Usage: ```sh ./xsct 4000 0.5 && ./xsct ``` Fixes #32 .
1 parent 1bfe075 commit f2aa7c8

File tree

6 files changed

+140
-82
lines changed

6 files changed

+140
-82
lines changed
 

‎CHANGELOG

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
PROJECT: https://github.com/faf0/sct
22

3+
1.9: zvezdochiot on 15 Dec 2022
4+
* Add [brightness] - linear brightness {0.0 .. 1.0}
5+
36
1.8.1: Ionic and faf0 on 27 Jul 2022
47
* Allow Makefile default settings to be overridden by environment variables; patch
58
contributed by Ionic

‎Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ MAN ?= $(PREFIX)/share/man/man1
77
INSTALL ?= install
88

99
PROG = xsct
10-
SRCS = xsct.c
10+
SRCS = src/xsct.c
1111

1212
LIBS = -lX11 -lXrandr -lm
1313

‎README.md

+9-5
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,18 @@ gcc -Wall -Wextra -Werror -pedantic -std=c99 -O2 -I /usr/X11R6/include xsct.c -o
8080

8181
Provided that xsct binary is located in your `$PATH`, execute it using the following command:
8282
~~~sh
83-
xsct 3700
83+
xsct 3700 0.9
8484
~~~
8585

86-
The first parameter (`3700` above) represents the color temperature.
86+
The first parameter (`3700` above) represents the color temperature.
8787

88-
If `xsct` is called with parameter 0, the color temperature is set to `6500`.
88+
The second parameter (`0.9` above) represents the brightness. The values are in the range `[0.0, 1.0]`.
8989

90-
If `xsct` is called without parameters, the current display temperature is estimated.
90+
If `xsct` is called with parameter 0, the color temperature is set to `6500`.
91+
92+
If `xsct` is called with the color temperature parameter only, the brightness is set to `1.0`.
93+
94+
If `xsct` is called without parameters, the current display temperature and brightness are estimated.
9195

9296
The following options, which can be specified before the optional temperature parameter, are supported:
9397
- `-h`, `--help`: display the help page
@@ -98,7 +102,7 @@ The following options, which can be specified before the optional temperature pa
98102

99103
Test xsct using the following command:
100104
~~~sh
101-
xsct 3700 && xsct
105+
xsct 3700 0.9 && xsct
102106
~~~
103107

104108
# Resources

‎xsct.c ‎src/xsct.c

+64-74
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,46 @@
44
* Public domain, do as you wish.
55
*/
66

7-
#include <X11/Xatom.h>
8-
#include <X11/Xlib.h>
9-
#include <X11/Xproto.h>
10-
#include <X11/extensions/Xrandr.h>
11-
12-
#include <stdio.h>
13-
#include <stdlib.h>
14-
#include <string.h>
15-
#include <math.h>
7+
#include "xsct.h"
168

179
static void usage(char * pname)
1810
{
19-
printf("Xsct (1.8)\n"
20-
"Usage: %s [options] [temperature]\n"
11+
printf("Xsct (%s)\n"
12+
"Usage: %s [options] [temperature] [brightness]\n"
2113
"\tIf the argument is 0, xsct resets the display to the default temperature (6500K)\n"
22-
"\tIf no arguments are passed, xsct estimates the current display temperature\n"
14+
"\tIf no arguments are passed, xsct estimates the current display temperature and brightness\n"
2315
"Options:\n"
2416
"\t-h, --help \t xsct will display this usage information\n"
2517
"\t-v, --verbose \t xsct will display debugging information\n"
2618
"\t-d, --delta\t xsct will shift temperature by the temperature value\n"
2719
"\t-s, --screen N\t xsct will only select screen specified by given zero-based index\n"
28-
"\t-c, --crtc N\t xsct will only select CRTC specified by given zero-based index\n", pname);
20+
"\t-c, --crtc N\t xsct will only select CRTC specified by given zero-based index\n", XSCT_VERSION, pname);
2921
}
3022

31-
#define TEMPERATURE_NORM 6500
32-
#define TEMPERATURE_ZERO 700
33-
#define GAMMA_MULT 65535.0
34-
// Approximation of the `redshift` table from
35-
// https://github.com/jonls/redshift/blob/04760afe31bff5b26cf18fe51606e7bdeac15504/src/colorramp.c#L30-L273
36-
// without limits:
37-
// GAMMA = K0 + K1 * ln(T - T0)
38-
// Red range (T0 = TEMPERATURE_ZERO)
39-
// Green color
40-
#define GAMMA_K0GR -1.47751309139817
41-
#define GAMMA_K1GR 0.28590164772055
42-
// Blue color
43-
#define GAMMA_K0BR -4.38321650114872
44-
#define GAMMA_K1BR 0.6212158769447
45-
// Blue range (T0 = TEMPERATURE_NORM - TEMPERATURE_ZERO)
46-
// Red color
47-
#define GAMMA_K0RB 1.75390204039018
48-
#define GAMMA_K1RB -0.1150805671482
49-
// Green color
50-
#define GAMMA_K0GB 1.49221604915144
51-
#define GAMMA_K1GB -0.07513509588921
52-
5323
static double DoubleTrim(double x, double a, double b)
5424
{
5525
double buff[3] = {a, x, b};
5626
return buff[ (int)(x > a) + (int)(x > b) ];
5727
}
5828

59-
static int get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug)
29+
static struct temp_status get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug)
6030
{
6131
Window root = RootWindow(dpy, screen);
6232
XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
6333

64-
int temp = 0, n, c;
34+
int n, c;
6535
double t = 0.0;
66-
double gammar = 0.0, gammag = 0.0, gammab = 0.0, gammam = 1.0, gammad = 0.0;
36+
double gammar = 0.0, gammag = 0.0, gammab = 0.0, gammad = 0.0;
37+
struct temp_status temp;
38+
temp.temp = 0;
39+
temp.brightness = 1.0;
6740

6841
n = res->ncrtc;
69-
int icrtc_specified = icrtc >= 0 && icrtc < n;
70-
for (c = icrtc_specified ? icrtc : 0; c < (icrtc_specified ? icrtc + 1 : n); c++)
42+
if ((icrtc >= 0) && (icrtc < n))
43+
n = 1;
44+
else
45+
icrtc = 0;
46+
for (c = icrtc; c < (icrtc + n); c++)
7147
{
7248
RRCrtc crtcxid;
7349
int size;
@@ -82,14 +58,17 @@ static int get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug)
8258
XRRFreeGamma(crtc_gamma);
8359
}
8460
XFree(res);
85-
gammam = (gammar > gammag) ? gammar : gammag;
86-
gammam = (gammab > gammam) ? gammab : gammam;
87-
if (gammam > 0.0)
61+
temp.brightness = (gammar > gammag) ? gammar : gammag;
62+
temp.brightness = (gammab > temp.brightness) ? gammab : temp.brightness;
63+
if (temp.brightness > 0.0 && n > 0)
8864
{
89-
gammar /= gammam;
90-
gammag /= gammam;
91-
gammab /= gammam;
92-
if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f\n", gammar, gammag, gammab);
65+
gammar /= temp.brightness;
66+
gammag /= temp.brightness;
67+
gammab /= temp.brightness;
68+
temp.brightness /= n;
69+
temp.brightness /= BRIGHTHESS_DIV;
70+
temp.brightness = DoubleTrim(temp.brightness, 0.0, 1.0);
71+
if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f, brightness: %f\n", gammar, gammag, gammab, temp.brightness);
9372
gammad = gammab - gammar;
9473
if (gammad < 0.0)
9574
{
@@ -107,34 +86,37 @@ static int get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug)
10786
t = exp((gammag + 1.0 - gammad - (GAMMA_K0GB + GAMMA_K0RB)) / (GAMMA_K1GB + GAMMA_K1RB)) + (TEMPERATURE_NORM - TEMPERATURE_ZERO);
10887
}
10988
}
89+
else
90+
temp.brightness = DoubleTrim(temp.brightness, 0.0, 1.0);
11091

111-
temp = (int)(t + 0.5);
92+
temp.temp = (int)(t + 0.5);
11293

11394
return temp;
11495
}
11596

116-
static void sct_for_screen(Display *dpy, int screen, int icrtc, int temp, int fdebug)
97+
static void sct_for_screen(Display *dpy, int screen, int icrtc, struct temp_status temp, int fdebug)
11798
{
118-
double t = 0.0, g = 0.0, gammar, gammag, gammab;
99+
double t = 0.0, b = 1.0, g = 0.0, gammar, gammag, gammab;
119100
int n, c;
120101
Window root = RootWindow(dpy, screen);
121102
XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
122103

123-
t = (double)temp;
124-
if (temp < TEMPERATURE_NORM)
104+
t = (double)temp.temp;
105+
b = DoubleTrim(temp.brightness, 0.0, 1.0);
106+
if (temp.temp < TEMPERATURE_NORM)
125107
{
126108
gammar = 1.0;
127-
if (temp < TEMPERATURE_ZERO)
128-
{
129-
gammag = 0.0;
130-
gammab = 0.0;
131-
}
132-
else
109+
if (temp.temp > TEMPERATURE_ZERO)
133110
{
134111
g = log(t - TEMPERATURE_ZERO);
135112
gammag = DoubleTrim(GAMMA_K0GR + GAMMA_K1GR * g, 0.0, 1.0);
136113
gammab = DoubleTrim(GAMMA_K0BR + GAMMA_K1BR * g, 0.0, 1.0);
137114
}
115+
else
116+
{
117+
gammag = 0.0;
118+
gammab = 0.0;
119+
}
138120
}
139121
else
140122
{
@@ -143,10 +125,13 @@ static void sct_for_screen(Display *dpy, int screen, int icrtc, int temp, int fd
143125
gammag = DoubleTrim(GAMMA_K0GB + GAMMA_K1GB * g, 0.0, 1.0);
144126
gammab = 1.0;
145127
}
146-
if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f\n", gammar, gammag, gammab);
128+
if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f, brightness: %f\n", gammar, gammag, gammab, b);
147129
n = res->ncrtc;
148-
int icrtc_specified = icrtc >= 0 && icrtc < n;
149-
for (c = icrtc_specified ? icrtc : 0; c < (icrtc_specified ? icrtc + 1 : n); c++)
130+
if ((icrtc >= 0) && (icrtc < n))
131+
n = 1;
132+
else
133+
icrtc = 0;
134+
for (c = icrtc; c < (icrtc + n); c++)
150135
{
151136
int size, i;
152137
RRCrtc crtcxid;
@@ -158,7 +143,7 @@ static void sct_for_screen(Display *dpy, int screen, int icrtc, int temp, int fd
158143

159144
for (i = 0; i < size; i++)
160145
{
161-
g = GAMMA_MULT * (double)i / (double)size;
146+
g = GAMMA_MULT * b * (double)i / (double)size;
162147
crtc_gamma->red[i] = (unsigned short int)(g * gammar + 0.5);
163148
crtc_gamma->green[i] = (unsigned short int)(g * gammag + 0.5);
164149
crtc_gamma->blue[i] = (unsigned short int)(g * gammab + 0.5);
@@ -173,8 +158,9 @@ static void sct_for_screen(Display *dpy, int screen, int icrtc, int temp, int fd
173158

174159
int main(int argc, char **argv)
175160
{
176-
int i, screen, screens, temp;
161+
int i, screen, screens;
177162
int screen_specified, screen_first, screen_last, crtc_specified;
163+
struct temp_status temp;
178164
int fdebug = 0, fdelta = 0, fhelp = 0;
179165
Display *dpy = XOpenDisplay(NULL);
180166

@@ -187,9 +173,10 @@ int main(int argc, char **argv)
187173
screens = XScreenCount(dpy);
188174
screen_first = 0;
189175
screen_last = screens - 1;
190-
temp = -1;
191176
screen_specified = -1;
192177
crtc_specified = -1;
178+
temp.temp = DELTA_MIN;
179+
temp.brightness = -1.0;
193180
for (i = 1; i < argc; i++)
194181
{
195182
if ((strcmp(argv[i],"-h") == 0) || (strcmp(argv[i],"--help") == 0)) fhelp = 1;
@@ -217,7 +204,8 @@ int main(int argc, char **argv)
217204
fhelp = 1;
218205
}
219206
}
220-
else if (temp == -1) temp = atoi(argv[i]);
207+
else if (temp.temp == DELTA_MIN) temp.temp = atoi(argv[i]);
208+
else if (temp.brightness < 0.0) temp.brightness = atof(argv[i]);
221209
else
222210
{
223211
fprintf(stderr, "ERROR! Unknown parameter: %s\n!", argv[i]);
@@ -235,33 +223,34 @@ int main(int argc, char **argv)
235223
}
236224
else
237225
{
226+
if (temp.brightness < 0.0) temp.brightness = 1.0;
238227
if (screen_specified >= 0)
239228
{
240229
screen_first = screen_specified;
241230
screen_last = screen_specified;
242231
}
243-
if ((temp < 0) && (fdelta == 0))
232+
if ((temp.temp < 0) && (fdelta == 0))
244233
{
245234
// No arguments, so print estimated temperature for each screen
246235
for (screen = screen_first; screen <= screen_last; screen++)
247236
{
248237
temp = get_sct_for_screen(dpy, screen, crtc_specified, fdebug);
249-
printf("Screen %d: temperature ~ %d\n", screen, temp);
238+
printf("Screen %d: temperature ~ %d %f\n", screen, temp.temp, temp.brightness);
250239
}
251240
}
252241
else
253242
{
254243
if (fdelta == 0)
255244
{
256245
// Set temperature to given value or default for a value of 0
257-
if (temp == 0)
246+
if (temp.temp == 0)
258247
{
259-
temp = TEMPERATURE_NORM;
248+
temp.temp = TEMPERATURE_NORM;
260249
}
261-
else if (temp < TEMPERATURE_ZERO)
250+
else if (temp.temp < TEMPERATURE_ZERO)
262251
{
263252
fprintf(stderr, "WARNING! Temperatures below %d cannot be displayed.\n", TEMPERATURE_ZERO);
264-
temp = TEMPERATURE_ZERO;
253+
temp.temp = TEMPERATURE_ZERO;
265254
}
266255
for (screen = screen_first; screen <= screen_last; screen++)
267256
{
@@ -273,11 +262,12 @@ int main(int argc, char **argv)
273262
// Delta mode: Shift temperature of each screen by given value
274263
for (screen = screen_first; screen <= screen_last; screen++)
275264
{
276-
int tempd = temp + get_sct_for_screen(dpy, screen, crtc_specified, fdebug);
277-
if (tempd < TEMPERATURE_ZERO)
265+
struct temp_status tempd = get_sct_for_screen(dpy, screen, crtc_specified, fdebug);
266+
tempd.temp += temp.temp;
267+
if (tempd.temp < TEMPERATURE_ZERO)
278268
{
279269
fprintf(stderr, "WARNING! Temperatures below %d cannot be displayed.\n", TEMPERATURE_ZERO);
280-
tempd = TEMPERATURE_ZERO;
270+
tempd.temp = TEMPERATURE_ZERO;
281271
}
282272
sct_for_screen(dpy, screen, crtc_specified, tempd, fdebug);
283273
}

‎src/xsct.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* xsct - X11 set color temperature
3+
*
4+
* Public domain, do as you wish.
5+
*/
6+
7+
#include <X11/Xatom.h>
8+
#include <X11/Xlib.h>
9+
#include <X11/Xproto.h>
10+
#include <X11/extensions/Xrandr.h>
11+
12+
#include <stdio.h>
13+
#include <stdlib.h>
14+
#include <string.h>
15+
#include <math.h>
16+
17+
#ifndef __XSCT_H
18+
#define __XSCT_H
19+
20+
#define XSCT_VERSION "1.9"
21+
22+
#define TEMPERATURE_NORM 6500
23+
#define TEMPERATURE_ZERO 700
24+
#define GAMMA_MULT 65535.0
25+
// Approximation of the `redshift` table from
26+
// https://github.com/jonls/redshift/blob/04760afe31bff5b26cf18fe51606e7bdeac15504/src/colorramp.c#L30-L273
27+
// without limits:
28+
// GAMMA = K0 + K1 * ln(T - T0)
29+
// Red range (T0 = TEMPERATURE_ZERO)
30+
// Green color
31+
#define GAMMA_K0GR -1.47751309139817
32+
#define GAMMA_K1GR 0.28590164772055
33+
// Blue color
34+
#define GAMMA_K0BR -4.38321650114872
35+
#define GAMMA_K1BR 0.6212158769447
36+
// Blue range (T0 = TEMPERATURE_NORM - TEMPERATURE_ZERO)
37+
// Red color
38+
#define GAMMA_K0RB 1.75390204039018
39+
#define GAMMA_K1RB -0.1150805671482
40+
// Green color
41+
#define GAMMA_K0GB 1.49221604915144
42+
#define GAMMA_K1GB -0.07513509588921
43+
#define BRIGHTHESS_DIV 65470.988
44+
#define DELTA_MIN -1000000
45+
46+
struct temp_status
47+
{
48+
int temp;
49+
double brightness;
50+
};
51+
52+
static void usage(char * pname);
53+
static double DoubleTrim(double x, double a, double b);
54+
static struct temp_status get_sct_for_screen(Display *dpy, int screen, int icrtc, int fdebug);
55+
static void sct_for_screen(Display *dpy, int screen, int icrtc, struct temp_status temp, int fdebug);
56+
57+
#endif /* __XSCT_H */
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Please sign in to comment.