sct

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

Commit: 2efda0e802cfeaf376ec6437b0a94acc4baef633
Parent: 289bfab6d2ea5f1c6733a4c65b112aafcb39f91f
Author: zvezdochiot
Date:   Fri,  9 Aug 2019 16:41:27 +0300

1.5: simplify code

Diffstat:
MMakefile | 2+-
Dsct.c | 239-------------------------------------------------------------------------------
Axsct.c | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 235 insertions(+), 240 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,7 +2,7 @@ PROG = xsct CC = gcc CFLAGS = -Wall -Wextra -Werror -pedantic -std=c99 -O2 -I /usr/X11R6/include LDFLAGS = -L /usr/X11R6/lib -lX11 -lXrandr -lm -s -SRCS = sct.c +SRCS = xsct.c PREFIX = /usr BIN = $(PREFIX)/bin MAN = $(PREFIX)/share/man/man1 diff --git a/sct.c b/sct.c @@ -1,239 +0,0 @@ -/* - * xsct - X11 set color temperature - * - * 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 - * - * Original code published by Ted Unangst: - * http://www.tedunangst.com/flak/post/sct-set-color-temperature - * - * Modified by Fabian Foerg in order to: - * - compile on Ubuntu 14.04 - * - iterate over all screens of the default display and change the color - * temperature - * - fix memleaks - * - clean up code - * - return EXIT_SUCCESS - * - * Public domain, do as you wish. - * - * gcc -Wall -Wextra -Werror -pedantic -std=c99 -O2 -I /usr/X11R6/include sct.c -o xsct -L /usr/X11R6/lib -lX11 -lXrandr -lm -s - * - */ - -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/Xproto.h> -#include <X11/extensions/Xrandr.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> - -static void usage(char * pname) -{ - printf("Xsct (1.5)\n" - "Usage: %s [options] [temperature]\n" - "\tIf the argument is 0, xsct resets the display to the default temperature (6500K)\n" - "\tIf no arguments are passed, xsct estimates the current display temperature\n" - "Options:\n" - "\t-v, --verbose \t xsct will display debugging information\n" - "\t-h, --help \t xsct will display this usage information\n", pname); -} - -#define TEMPERATURE_NORM 6500 -#define TEMPERATURE_ZERO 700 -#define GAMMA_MULT 65535.0 -// Approximation of the `redshift` table from -// https://github.com/jonls/redshift/blob/04760afe31bff5b26cf18fe51606e7bdeac15504/src/colorramp.c#L30-L273 -// without limits: -// GAMMA = K0 + K1 * ln(T - T0) - // Red range (T0 = TEMPERATURE_ZERO) - // Green color -#define GAMMA_K0GR -1.47751309139817 -#define GAMMA_K1GR 0.28590164772055 - // Blue color -#define GAMMA_K0BR -4.38321650114872 -#define GAMMA_K1BR 0.6212158769447 - // Blue range (T0 = TEMPERATURE_NORM - TEMPERATURE_ZERO) - // Red color -#define GAMMA_K0RB 1.75390204039018 -#define GAMMA_K1RB -0.1150805671482 - // Green color -#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[ (int)(x > a) + (int)(x > b) ]; -} - -static int get_sct_for_screen(Display *dpy, int screen, int fdebug) -{ - Window root = RootWindow(dpy, screen); - XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); - - 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; - - n = res->ncrtc; - for (c = 0; c < n; c++) - { - RRCrtc crtcxid; - int size; - XRRCrtcGamma *crtc_gamma; - crtcxid = res->crtcs[c]; - crtc_gamma = XRRGetCrtcGamma(dpy, crtcxid); - size = crtc_gamma->size; - gammar += (crtc_gamma->red[size - 1]); - gammag += (crtc_gamma->green[size - 1]); - gammab += (crtc_gamma->blue[size - 1]); - - XRRFreeGamma(crtc_gamma); - } - XFree(res); - gammam = (gammar > gammag) ? gammar : gammag; - gammam = (gammab > gammam) ? gammab : gammam; - if (gammam > 0.0) - { - gammar /= gammam; - gammag /= gammam; - gammab /= gammam; - if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f\n", gammar, gammag, gammab); - gammad = gammab - gammar; - if (gammad < 0.0) - { - if (gammab > 0.0) - { - t = gammag + gammad + 1.0; - t -= (GAMMA_K0GR + GAMMA_K0BR); - t /= (GAMMA_K1GR + GAMMA_K1BR); - t = exp(t); - t += TEMPERATURE_ZERO; - } else { - if (gammag > 0.0) - { - t = gammag; - t -= GAMMA_K0GR; - t /= GAMMA_K1GR; - t = exp(t); - t += TEMPERATURE_ZERO; - } else { - 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); - } - } - - temp = (int)(t + 0.5); - - return temp; -} - -static void sct_for_screen(Display *dpy, int screen, int temp, int fdebug) -{ - double t = 0.0, g = 0.0, gammar, gammag, gammab; - int n, c; - Window root = RootWindow(dpy, screen); - XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); - - 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; - } - if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f\n", gammar, gammag, gammab); - - n = res->ncrtc; - for (c = 0; c < n; c++) - { - int size, i; - RRCrtc crtcxid; - XRRCrtcGamma *crtc_gamma; - crtcxid = res->crtcs[c]; - size = XRRGetCrtcGammaSize(dpy, crtcxid); - - crtc_gamma = XRRAllocGamma(size); - - for (i = 0; i < size; i++) - { - g = GAMMA_MULT * (double)i / (double)size; - crtc_gamma->red[i] = (unsigned short int)(g * gammar + 0.5); - crtc_gamma->green[i] = (unsigned short int)(g * gammag + 0.5); - crtc_gamma->blue[i] = (unsigned short int)(g * gammab + 0.5); - } - - XRRSetCrtcGamma(dpy, crtcxid, crtc_gamma); - XRRFreeGamma(crtc_gamma); - } - - XFree(res); -} - -int main(int argc, char **argv) -{ - int i, screen, screens, temp; - int fdebug = 0, fhelp = 0; - Display *dpy = XOpenDisplay(NULL); - if (!dpy) { - perror("XOpenDisplay(NULL) failed"); - fprintf(stderr, "Make sure DISPLAY is set correctly.\n"); - return EXIT_FAILURE; - } - screens = XScreenCount(dpy); - - temp = -1; - for (i = 1; i < argc; i++) - { - if ((strcmp(argv[i],"-v") == 0) || (strcmp(argv[i],"--verbose") == 0)) fdebug = 1; - else if ((strcmp(argv[i],"-h") == 0) || (strcmp(argv[i],"--help") == 0)) fhelp = 1; - else temp = atoi(argv[i]); - } - if (fhelp > 0) - { - usage(argv[0]); - } else { - if (temp < 0) - { - for (screen = 0; screen < screens; screen++) - { - temp = get_sct_for_screen(dpy, screen, fdebug); - printf("Screen %d: temperature ~ %d\n", screen, temp); - } - } else { - if (temp == 0) - temp = TEMPERATURE_NORM; - - for (screen = 0; screen < screens; screen++) - sct_for_screen(dpy, screen, temp, fdebug); - } - } - - XCloseDisplay(dpy); - - return EXIT_SUCCESS; -} - diff --git a/xsct.c b/xsct.c @@ -0,0 +1,234 @@ +/* + * xsct - X11 set color temperature + * + * 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 + * + * Original code published by Ted Unangst: + * http://www.tedunangst.com/flak/post/sct-set-color-temperature + * + * Modified by Fabian Foerg in order to: + * - compile on Ubuntu 14.04 + * - iterate over all screens of the default display and change the color + * temperature + * - fix memleaks + * - clean up code + * - return EXIT_SUCCESS + * + * Public domain, do as you wish. + * + * gcc -Wall -Wextra -Werror -pedantic -std=c99 -O2 -I /usr/X11R6/include sct.c -o xsct -L /usr/X11R6/lib -lX11 -lXrandr -lm -s + * + */ + +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xproto.h> +#include <X11/extensions/Xrandr.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +static void usage(char * pname) +{ + printf("Xsct (1.5)\n" + "Usage: %s [options] [temperature]\n" + "\tIf the argument is 0, xsct resets the display to the default temperature (6500K)\n" + "\tIf no arguments are passed, xsct estimates the current display temperature\n" + "Options:\n" + "\t-v, --verbose \t xsct will display debugging information\n" + "\t-h, --help \t xsct will display this usage information\n", pname); +} + +#define TEMPERATURE_NORM 6500 +#define TEMPERATURE_ZERO 700 +#define GAMMA_MULT 65535.0 +// Approximation of the `redshift` table from +// https://github.com/jonls/redshift/blob/04760afe31bff5b26cf18fe51606e7bdeac15504/src/colorramp.c#L30-L273 +// without limits: +// GAMMA = K0 + K1 * ln(T - T0) +// Red range (T0 = TEMPERATURE_ZERO) +// Green color +#define GAMMA_K0GR -1.47751309139817 +#define GAMMA_K1GR 0.28590164772055 +// Blue color +#define GAMMA_K0BR -4.38321650114872 +#define GAMMA_K1BR 0.6212158769447 +// Blue range (T0 = TEMPERATURE_NORM - TEMPERATURE_ZERO) +// Red color +#define GAMMA_K0RB 1.75390204039018 +#define GAMMA_K1RB -0.1150805671482 +// Green color +#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[ (int)(x > a) + (int)(x > b) ]; +} + +static int get_sct_for_screen(Display *dpy, int screen, int fdebug) +{ + Window root = RootWindow(dpy, screen); + XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); + + 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; + + n = res->ncrtc; + for (c = 0; c < n; c++) + { + RRCrtc crtcxid; + int size; + XRRCrtcGamma *crtc_gamma; + crtcxid = res->crtcs[c]; + crtc_gamma = XRRGetCrtcGamma(dpy, crtcxid); + size = crtc_gamma->size; + gammar += (crtc_gamma->red[size - 1]); + gammag += (crtc_gamma->green[size - 1]); + gammab += (crtc_gamma->blue[size - 1]); + + XRRFreeGamma(crtc_gamma); + } + XFree(res); + gammam = (gammar > gammag) ? gammar : gammag; + gammam = (gammab > gammam) ? gammab : gammam; + if (gammam > 0.0) + { + gammar /= gammam; + gammag /= gammam; + gammab /= gammam; + if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f\n", gammar, gammag, gammab); + gammad = gammab - gammar; + if (gammad < 0.0) + { + if (gammab > 0.0) + { + t = exp((gammag + 1.0 + gammad - (GAMMA_K0GR + GAMMA_K0BR)) / (GAMMA_K1GR + GAMMA_K1BR)) + TEMPERATURE_ZERO; + } + else + { + t = (gammag > 0.0) ? (exp((gammag - GAMMA_K0GR) / GAMMA_K1GR) + TEMPERATURE_ZERO) : TEMPERATURE_ZERO; + } + } + else + { + t = exp((gammag + 1.0 - gammad - (GAMMA_K0GB + GAMMA_K0RB)) / (GAMMA_K1GB + GAMMA_K1RB)) + (TEMPERATURE_NORM - TEMPERATURE_ZERO); + } + } + + temp = (int)(t + 0.5); + + return temp; +} + +static void sct_for_screen(Display *dpy, int screen, int temp, int fdebug) +{ + double t = 0.0, g = 0.0, gammar, gammag, gammab; + int n, c; + Window root = RootWindow(dpy, screen); + XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); + + 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; + } + if (fdebug > 0) fprintf(stderr, "DEBUG: Gamma: %f, %f, %f\n", gammar, gammag, gammab); + + n = res->ncrtc; + for (c = 0; c < n; c++) + { + int size, i; + RRCrtc crtcxid; + XRRCrtcGamma *crtc_gamma; + crtcxid = res->crtcs[c]; + size = XRRGetCrtcGammaSize(dpy, crtcxid); + + crtc_gamma = XRRAllocGamma(size); + + for (i = 0; i < size; i++) + { + g = GAMMA_MULT * (double)i / (double)size; + crtc_gamma->red[i] = (unsigned short int)(g * gammar + 0.5); + crtc_gamma->green[i] = (unsigned short int)(g * gammag + 0.5); + crtc_gamma->blue[i] = (unsigned short int)(g * gammab + 0.5); + } + + XRRSetCrtcGamma(dpy, crtcxid, crtc_gamma); + XRRFreeGamma(crtc_gamma); + } + + XFree(res); +} + +int main(int argc, char **argv) +{ + int i, screen, screens, temp; + int fdebug = 0, fhelp = 0; + Display *dpy = XOpenDisplay(NULL); + if (!dpy) + { + perror("XOpenDisplay(NULL) failed"); + fprintf(stderr, "Make sure DISPLAY is set correctly.\n"); + return EXIT_FAILURE; + } + screens = XScreenCount(dpy); + + temp = -1; + for (i = 1; i < argc; i++) + { + if ((strcmp(argv[i],"-v") == 0) || (strcmp(argv[i],"--verbose") == 0)) fdebug = 1; + else if ((strcmp(argv[i],"-h") == 0) || (strcmp(argv[i],"--help") == 0)) fhelp = 1; + else temp = atoi(argv[i]); + } + if (fhelp > 0) + { + usage(argv[0]); + } + else + { + if (temp < 0) + { + for (screen = 0; screen < screens; screen++) + { + temp = get_sct_for_screen(dpy, screen, fdebug); + printf("Screen %d: temperature ~ %d\n", screen, temp); + } + } + else + { + temp = (temp == 0) ? TEMPERATURE_NORM : temp; + + for (screen = 0; screen < screens; screen++) + sct_for_screen(dpy, screen, temp, fdebug); + } + } + + XCloseDisplay(dpy); + + return EXIT_SUCCESS; +} +