Commit: 7c13a4869eaea10cd138ab616c873b0226a5ff7f
Parent: a38a0df3f85e0c437de3a28cf1627bcae68ef4ff
Author: zvezdochiot
Date: Wed, 7 Aug 2019 10:23:02 +0300
fix #9: 1.5: Approximation of the redshift table (no limits)
Diffstat:
5 files changed, 108 insertions(+), 60 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -1,5 +1,11 @@
PROJECT: https://github.com/faf0/sct
+1.5: zvezdochiot on 07 Aug 2019
+* Approximation of the `redshift` table (no limits)
+
+1.4: zvezdochiot on 04 Aug 2019
+* Read current temperature
+
1.3: zvezdochiot on 02 Jan 2019
* Rename utilites for X11
* Add -h option to print usage information
diff --git a/Makefile b/Makefile
@@ -1,7 +1,7 @@
PROG = xsct
CC = gcc
CFLAGS = -Wall -std=c99 -O2 -I /usr/X11R6/include
-LDFLAGS = -L /usr/X11R6/lib -lX11 -lXrandr
+LDFLAGS = -L /usr/X11R6/lib -lX11 -lXrandr -lm
SRCS = sct.c
PREFIX = /usr
BIN = $(PREFIX)/bin
diff --git a/README.md b/README.md
@@ -20,7 +20,7 @@ Minor modifications were made in order to get sct to:
Compile the code using the following command:
~~~
-cc -std=c99 -O2 -I /usr/X11R6/include sct.c -o xsct -L /usr/X11R6/lib -lX11 -lXrandr
+gcc -Wall -std=c99 -O2 -I /usr/X11R6/include sct.c -o xsct -L /usr/X11R6/lib -lX11 -lXrandr -lm -s
~~~
Execute sct using the following command:
@@ -34,6 +34,12 @@ between `1000` and `10000`.
If `xsct` is called with parameter 0, the color temperature is set to `6500`.
If `xsct` is called without parameters, the current display temperature is estimated.
+Test sct using the following command:
+
+~~~
+./xsct 3700 && ./xsct
+~~~
+
---
https://github.com/faf0/sct/
diff --git a/sct.c b/sct.c
@@ -16,6 +16,9 @@
* - return EXIT_SUCCESS
*
* Public domain, do as you wish.
+ *
+ * gcc -Wall -std=c99 -O2 -I /usr/X11R6/include sct.c -o xsct -L /usr/X11R6/lib -lX11 -lXrandr -lm -s
+ *
*/
#include <X11/Xatom.h>
@@ -26,6 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
static void usage()
{
@@ -36,83 +40,115 @@ static void usage()
"If -h or --help is passed xsct will display this usage information\n");
}
-/* cribbed from redshift, but truncated with 500K steps */
-static const struct { float r; float g; float b; } whitepoints[] = {
- { 1.00000000, 0.18172716, 0.00000000, }, /* 1000K */
- { 1.00000000, 0.42322816, 0.00000000, },
- { 1.00000000, 0.54360078, 0.08679949, },
- { 1.00000000, 0.64373109, 0.28819679, },
- { 1.00000000, 0.71976951, 0.42860152, },
- { 1.00000000, 0.77987699, 0.54642268, },
- { 1.00000000, 0.82854786, 0.64816570, },
- { 1.00000000, 0.86860704, 0.73688797, },
- { 1.00000000, 0.90198230, 0.81465502, },
- { 1.00000000, 0.93853986, 0.88130458, },
- { 1.00000000, 0.97107439, 0.94305985, },
- { 1.00000000, 1.00000000, 1.00000000, }, /* 6500K */
- { 0.95160805, 0.96983355, 1.00000000, },
- { 0.91194747, 0.94470005, 1.00000000, },
- { 0.87906581, 0.92357340, 1.00000000, },
- { 0.85139976, 0.90559011, 1.00000000, },
- { 0.82782969, 0.89011714, 1.00000000, },
- { 0.80753191, 0.87667891, 1.00000000, },
- { 0.78988728, 0.86491137, 1.00000000, }, /* 10000K */
- { 0.77442176, 0.85453121, 1.00000000, },
-};
-#define TEMPERATURE_DEFAULT 6500
-#define TEMPERATURE_MIN 1000
-#define TEMPERATURE_MAX 10000
-#define TEMPERATURE_STEP 500
+#define TEMPERATURE_NORM 6500
+#define TEMPERATURE_ZERO 700
#define GAMMA_MULT 65535.0
-#define AVG(c,temp,ratio) whitepoints[(temp) / TEMPERATURE_STEP].c * (1 - (ratio)) + whitepoints[(temp) / TEMPERATURE_STEP + 1].c * (ratio)
+#define GAMMA_K0GR -1.47751309139817
+#define GAMMA_K1GR 0.28590164772055
+#define GAMMA_K0BR -4.38321650114872
+#define GAMMA_K1BR 0.6212158769447
+#define GAMMA_K0RB 1.75390204039018
+#define GAMMA_K1RB -0.1150805671482
+#define GAMMA_K0GB 1.49221604915144
+#define GAMMA_K1GB -0.07513509588921
+
+static double DoubleTrim(double x, double a, double b)
+{
+ double buff[3] = {a, x, b};
+ return buff[ (x > a) + (x > b) ];
+}
static int get_sct_for_screen(Display *dpy, int screen)
{
Window root = RootWindow(dpy, screen);
XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
- int temp = 0;
- double t, ts;
- double gammar, gammag, gammab;
+ int temp = 0, n, c;
+ double t = 0.0;
+ double gammar = 0.0, gammag = 0.0, gammab = 0.0, gammam = 1.0, gammad = 0.0;
- int n = res->ncrtc;
- ts = 0.0;
- for (int c = 0; c < n; c++)
+ n = res->ncrtc;
+ for (c = 0; c < n; c++)
{
int crtcxid = res->crtcs[c];
XRRCrtcGamma *crtc_gamma = XRRGetCrtcGamma(dpy, crtcxid);
int size = crtc_gamma->size;
+ gammar += (crtc_gamma->red[size - 1]);
+ gammag += (crtc_gamma->green[size - 1]);
+ gammab += (crtc_gamma->blue[size - 1]);
- if (size > 0)
+ XFree(crtc_gamma);
+ }
+ XFree(res);
+ gammam = (gammar > gammag) ? gammar : gammag;
+ gammam = (gammab > gammam) ? gammab : gammam;
+ if (gammam > 0.0)
+ {
+ gammar /= gammam;
+ gammag /= gammam;
+ gammab /= gammam;
+ gammad = gammab - gammar;
+ if (gammad < 0.0)
{
- double g_inv = (size + 1) / size / GAMMA_MULT;
- gammar = crtc_gamma->red[size - 1] * g_inv;
- gammag = crtc_gamma->green[size - 1] * g_inv;
- gammab = crtc_gamma->blue[size - 1] * g_inv;
- t = (64465 - 109049 * gammar + 46013 * gammar * gammar -
- 4322 * gammag + 10708 * gammag * gammag -
- 2662 * gammab + 1355 * gammab * gammab);
- ts += t;
+ if (gammab == 0.0)
+ {
+ if (gammag == 0.0)
+ {
+ t = TEMPERATURE_ZERO;
+ } else {
+ t = gammag;
+ t -= GAMMA_K0GR;
+ t /= GAMMA_K1GR;
+ t = exp(t);
+ t += TEMPERATURE_ZERO;
+ }
+ } else {
+ t = gammag + gammad + 1.0;
+ t -= (GAMMA_K0GR + GAMMA_K0BR);
+ t /= (GAMMA_K1GR + GAMMA_K1BR);
+ t = exp(t);
+ t += TEMPERATURE_ZERO;
+ }
+ } else {
+ t = gammag + 1.0 - gammad;
+ t -= (GAMMA_K0GB + GAMMA_K0RB);
+ t /= (GAMMA_K1GB + GAMMA_K1RB);
+ t = exp(t);
+ t += (TEMPERATURE_NORM - TEMPERATURE_ZERO);
}
-
- XFree(crtc_gamma);
}
- temp = (int)(ts / (double)n);
- XFree(res);
+ temp = (int)(t + 0.5);
+
return temp;
}
static void sct_for_screen(Display *dpy, int screen, int temp)
{
+ double t = 0.0, g = 0.0, gammar, gammag, gammab;
Window root = RootWindow(dpy, screen);
XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root);
- temp -= TEMPERATURE_MIN;
- double ratio = temp % TEMPERATURE_STEP / TEMPERATURE_STEP;
- double gammar = AVG(r, temp, ratio);
- double gammag = AVG(g, temp, ratio);
- double gammab = AVG(b, temp, ratio);
+ t = (double)temp;
+ if (temp < TEMPERATURE_NORM)
+ {
+ gammar = 1.0;
+ if (temp < TEMPERATURE_ZERO)
+ {
+ gammag = 0.0;
+ gammab = 0.0;
+ } else {
+ g = log(t - TEMPERATURE_ZERO);
+ gammag = DoubleTrim(GAMMA_K0GR + GAMMA_K1GR * g, 0.0, 1.0);
+ gammab = DoubleTrim(GAMMA_K0BR + GAMMA_K1BR * g, 0.0, 1.0);
+ }
+ } else {
+ g = log(t - (TEMPERATURE_NORM - TEMPERATURE_ZERO));
+ gammar = DoubleTrim(GAMMA_K0RB + GAMMA_K1RB * g, 0.0, 1.0);
+ gammag = DoubleTrim(GAMMA_K0GB + GAMMA_K1GB * g, 0.0, 1.0);
+ gammab = 1.0;
+
+ }
int n = res->ncrtc;
for (int c = 0; c < n; c++)
@@ -124,7 +160,7 @@ static void sct_for_screen(Display *dpy, int screen, int temp)
for (int i = 0; i < size; i++)
{
- double g = GAMMA_MULT * i / size;
+ g = GAMMA_MULT * (double)i / (double)size;
crtc_gamma->red[i] = g * gammar;
crtc_gamma->green[i] = g * gammag;
crtc_gamma->blue[i] = g * gammab;
@@ -147,7 +183,7 @@ int main(int argc, char **argv)
}
int screens = XScreenCount(dpy);
- int temp = TEMPERATURE_DEFAULT;
+ int temp = TEMPERATURE_NORM;
if (argc > 1)
{
if (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))
@@ -155,8 +191,8 @@ int main(int argc, char **argv)
usage();
} else {
temp = atoi(argv[1]);
- if (temp < TEMPERATURE_MIN || temp > TEMPERATURE_MAX)
- temp = TEMPERATURE_DEFAULT;
+ if (temp <= 0)
+ temp = TEMPERATURE_NORM;
for (int screen = 0; screen < screens; screen++)
sct_for_screen(dpy, screen, temp);
diff --git a/xsct.1 b/xsct.1
@@ -1,4 +1,4 @@
-.TH xsct 1 "Aug 2019" "1.4" "User Manual"
+.TH xsct 1 "Aug 2019" "1.5" "User Manual"
.SH NAME
xsct \- X11 set screen color temperature
.SH SYNOPSIS
@@ -13,7 +13,7 @@ or
.SH DESCRIPTION
.B xsct
-sets the screen's color temperature in a range from 1000 to 10000
+sets the screen's color temperature.
.SH OPTIONS
.IP temperature