sct

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

Commit: 2513bfa7e36e0fc2dcb4988b330d10d69fe168dc
Author: Fabian Foerg
Date:   Fri, 20 Nov 2015 19:32:42 -0500

Initial commit

Diffstat:
AREADME.md | 33+++++++++++++++++++++++++++++++++
Asct.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,33 @@ +# About + +Sct (set color temperature) is a UNIX tool which allows you to set the color +temperature of your screen. It is simpler than Redshift and f.lux. + +Original code was published by Ted Unangst: +http://www.tedunangst.com/flak/post/sct-set-color-temperature + +Minor modifications were made in order to get sct to: +- compile on Ubuntu 14.04 +- iterate over all screens of the default display and change the color + temperature +- free the Display structure +- return 0 + +# Installation + +Compile the code using the following command: + +~~~ +cc -std=c99 -O2 -I /usr/X11R6/include -o sct sct.c -L /usr/X11R6/lib -lm -lX11 -lXrandr +~~~ + +Execute sct using the following command: + +~~~ +./sct 3700 +~~~ + +The first parameter (`3700` above) denotes the color temperature and can be +between `1000` and `10000`. +If `sct` is called without parameters, sct sets the color temperature to `6500`. + diff --git a/sct.c b/sct.c @@ -0,0 +1,111 @@ +/* + * sct - set color temperature + * + * Compile the code using the following command: + * cc -std=c99 -O2 -I /usr/X11R6/include -o sct sct.c -L /usr/X11R6/lib -lm -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 + * - free the Display structure + * - return 0 + */ + +#include <inttypes.h> +#include <math.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xlibint.h> +#include <X11/Xproto.h> +#include <X11/extensions/Xrandr.h> +#include <X11/extensions/Xrender.h> + +/* 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, }, +}; + +static void +sct_for_screen(Display *dpy, int screen, int temp) +{ + Window root = RootWindow(dpy, screen); + XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); + + temp -= 1000; + double ratio = temp % 500 / 500.0; +#define AVG(c) whitepoints[temp / 500].c * (1 - ratio) + whitepoints[temp / 500 + 1].c * ratio + double gammar = AVG(r); + double gammag = AVG(g); + double gammab = AVG(b); + + int num_crtcs = res->ncrtc; + for (int c = 0; c < res->ncrtc; c++) { + int crtcxid = res->crtcs[c]; + XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(dpy, res, crtcxid); + + int size = XRRGetCrtcGammaSize(dpy, crtcxid); + + XRRCrtcGamma *crtc_gamma = XRRAllocGamma(size); + + for (int i = 0; i < size; i++) { + double g = 65535.0 * i / size; + crtc_gamma->red[i] = g * gammar; + crtc_gamma->green[i] = g * gammag; + crtc_gamma->blue[i] = g * gammab; + } + XRRSetCrtcGamma(dpy, crtcxid, crtc_gamma); + + XFree(crtc_gamma); + } +} + +int +main(int argc, char **argv) +{ + Display *dpy = XOpenDisplay(NULL); + int screens = XScreenCount(dpy); + + int temp = 6500; + if (argc > 1) + temp = atoi(argv[1]); + if (temp < 1000 || temp > 10000) + temp = 6500; + + for (int screen = 0; screen < screens; screen++) + sct_for_screen(dpy, screen, temp); + + XCloseDisplay(dpy); + + return 0; +} +