Correcting tedu's sct utility to set color temperature

Filed under: Software — Jacob Welsh @ 15:35

Some years ago, Ted Unangst - "tedu" of OpenBSD fame - posted(i) sct.c, a dead-simple program to adjust the color temperature of the video signal put out to the screen (or screens) of an X display, as an alternative to then-trending programs that came in binary-blob form or else invited in a large crowd of smelly dependencies. Light is a natural regulator of the circadian rhythms, and the idea is that exposure to blue light in particular promotes wakefulness, so one can reduce the disruptive effects of screen usage after sunset by toning down the blue. The program made its way into some of my systems and gets used at least on a somewhat regular basis.

It works by repurposing a longstanding feature of display controllers, the gamma correction table.(ii) Instead of computing a power curve for a given gamma value (exponent), sct loads a neutral, linear ramp (gamma=1) but scales the output range for the three color channels independently according to the requested temperature value in Kelvin. The mathematical function for computing red, green and blue scaling factors from the temperature is not shown, rather it does a linear interpolation between neighboring entries in a precomputed table. The neutral temperature where all channels get their full range is 6500K, with lower values (down to 1000) shifting redder and higher ones (up to 10000) bluer.

Recently, in assisting Robinson with an apparently failing sct, I discovered it was a bit too simple. It lacked proper error handling for the initial XOpenDisplay call, resulting in segfault by null pointer access when run without the necessary environment setup for connecting to an X display. Worse, it lacked any XFlush or XSync calls, or the implicit equivalent, meaning the commands it sent might never make it to the X server, depending on local buffering details. I worked out the appropriate fix for these problems, then since I was looking anyway, cleaned out some unused variables and header inclusions, and removed the insubstantial requirement to build in C99 mode. It probably took about an hour all told, from investigation to fix; so while the program may have turned out to be someone's quick and unloved hack, its small size at least brought the advantage of easy repair - requiring, of course, some decent knowledge of the much larger system it builds on.

Since his blog doesn't take comments, I suppose he gets to remain ignorant of both problems and fix.


Build & install:

$ gcc -o sct sct.c -lX11 -lXrandr
# cp sct /usr/local/bin/

You might need to add search paths for the X includes and libraries, for instance for my hand-built gentoo-based system:

$ gcc -o sct sct.c -I/usr/X11R7/include -L/usr/X11R7/lib -lX11 -lXrandr


$ sct 3000

To restore:

$ sct 6500

or simply

$ sct
  1. The link currently redirects to HTTPS, and he's a guy who ought to know better. [^]
  2. The old Cathode Ray Tube displays had a nonlinear response in light output versus applied voltage, meaning a correction was required for perceptually smooth grayscale and accurate color reproduction. Then sometimes it would get improperly corrected at some other processing stage, with "gamma" making its way into image formats, requiring an inverse correction in some cases; then LCD displays came along emulating the same response curve for compatibility, and who knows what manner of other confusions came up. [^]


  1. I built, tested and having been using on Ubuntu 16.04 (gcc 5.4, glibc 2.23 and binutils 2.26.1) and Gentoo (gcc 4.9.4, glibc 2.23 and binutils 2.25.1). Thanks.

    Comment by Robinson Dorion — 2023-03-25 @ 21:35

  2. @Robinson Dorion: possibly the xorg-server versions, display adapter (GPU) and driver would be the more interesting data here; but yes, it now seems to work everywhere it's tried and thanks for the report.

    Comment by Jacob Welsh — 2023-03-26 @ 20:45

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by MP-WP. Copyright Jacob Welsh.