sct

set color temperature
git clone anongit@rnpnr.xyz:sct.git
Log | Files | Refs | Feed | README | LICENSE

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:
MCHANGELOG | 6++++++
MMakefile | 2+-
MREADME.md | 8+++++++-
Msct.c | 148+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mxsct.1 | 4++--
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