How to use "xrandr --gamma" for Gnome "Night Light"-like usage?

Background: More red / Less blue at night

To save the eyes at night, adding more red and/or subtracting blue, is becoming popular in Windows 10 (blue-light filter) and Linux; Gnome Desktop (Night Light) and Ubuntu Unity Desktop with add-ons such as Red Shift or f.lux.

I'm wondering how to accomplish the same with Ubuntu's built-in command line xrandr <monitor> --gamma 1:1:1 feature. The 1:1:1 represents percentage of red:green:blue. I presume 1 = 100%. I'm not sure if the above packages add more red (1.2:1:1) for ~20% increase or reduce blue (1:1:0.8) for ~20% decrease or both for ~40% change.

Gnome Night Light example doesn't help

According to OMG Ubuntu, within Gnome's Night Light you can use these numerical values:

  • 1000 — Lowest value (super warm/red)
  • 4000 — Default night light on temperature
  • 5500 — Balanced night light temperature
  • 6500 — Default night light off temperature
  • 10000 — Highest value (super cool/blue)

To test these numerical values, how would does one translate them to override the default --gamma 1:1:1?

What xorg's documentation says

Xorg's documentation doesn't say very much about --gamma controls:

−−gamma red:green:blue

  • Set the specified floating point values as gamma correction on the crtc currently attached to this output. Note that you cannot get two different values for cloned outputs (i.e.: which share the same crtc) and that switching an output to another crtc doesn’t change the crtc gamma corrections at all.

Floating decimal points will be helpful because the script I want to upgrade sets xbacklight brightness slowly once a minute over a 90 to 120 minute transition period at dawn and dusk. I want to enhance the script with both xrandr --brightness software support for external monitors and OLED built in displays and xrandr --gamma support for red light / blue light filters. Xorg doesn't say how many decimal positions are supported but I think I think I will set bc calculations should be to 3 or 4 decimal positions for readability / precision balance.

Summary

I'm hoping to mimic what "the big guys" at Microsoft and Gnome are doing with their "more red" and/or "less blue" techniques. I haven't delved into Wayland yet but answers using that system will also be appreciated as it will no doubt be a future concern.

What adjustment to --gamma 1:1:1 are appropriate for night time?


Solution 1:

December 9, 2018 Update - sct

I found source code for program sct which allows user to set color temperature. It has "cribbed the code" from redshift and provides mapping for red, green and blue values:

/* 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, },
};

The three columns above are values for Red, Green and Blue.

November 4, 2018 Update - Eyesome

I wrote a collection of bash scripts called Eyesome that adjust brightness and gamma gradually at dawn and dusk over a 90 minute to 120 minute period. Although user can change the settings, a good starting point for full brightness setting is:

xrandr --output DP-1-1 --gamma 1:1:1 --brightness 1.0

The nighttime setting (for one of the three monitors) is:

xrandr --output DP-1-1 --gamma 1.0:0.88:0.76 --brightness 0.55

Note: Up to three monitors can be defined with separate settings.


Original Answer

Finally found one answer: MORE OF XRANDR OR BLUE LIGHT EXPOSURE This script is presented:

#!/bin/sh 

night_mode() { 
  for disp in $(xrandr | sed -n 's/^\([^ ]*\).*\<connected>.*/\1/p'); do 
    xrandr --output $disp --gamma $1 --brightness $2 
  done } 
case $1 in 
  off) night_mode 1:1:1 1.0 ;; 
  *) night_mode 1:1:0.5 0.7 ;;
esac

The script reduces blue light component and brightness of all Xorg displays attached. Simply save it in your bin directory, chmod +x it and, if you want to, add a cron job or keyboard shortcut to call the function.

How it works? Simply type in the script name without any parameters to reduce blue light. To return to normal setting, add off parameter after the command.

Solution 2:

Those values in the thousands you referred to are temperatures in Kelvin. Each has a corresponding black-body (a star or anything that emits all wavelengths of light) emission spectrum.

Black-body emission spectra

So, if you pick a band of visible light (red, green or blue, for example) then find where the curves intersect those bands and this gives you their proportions. (Note: the scale on the graph is logarithmic; the differences are much greater than they appear)

I think 5777K is our Sun (it is kind of white). Remember, this is just the raw emitted light, all kinds of atmospheric effects can bend or scatter or absorb light along the way at different times of day depending on the angle of the Sun, thickness of atmosphere, what chemicals are in the atmosphere, etc. Read this paper for more info on these phenomena: Variation of outdoor illumination as a function of solar elevation and light pollution .

You definitely don't need all this to make a nice gamma changing script but it's good to have some idea of what you are actually trying emulate then you can pick nice values.