Use-case: Enhance contrast when reading scanned document and document viewer does not support contrast adjustment.
<note warning>XF86VidModeSetGammaRamp is broken in recent X.org. I have created an ugly patch for redshift (apply, compile, run “./src/redshift -O 3000 white_threshold black_treshold”) to work around it.</note>
I was unable to find a tool that can fix this (tried xcalib, xgamma, xrandr and redshift). So I have created one myself. Unfortunately I don't know how to set contrast per window, so your whole X session is affected.
Compile:
gcc -std=gnu99 -O2 -g -ggdb3 -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lXxf86vm -lXext -o xlevels xlevels.c
Usage:
./xlevels white_threshold black_treshold
(it's the same syntax like in GIMP)
Examples:
./xlevels 100 255
./xlevels 50 230
xcalib -c
#include <stdlib.h> #include <stdio.h> #include <inttypes.h> #include <string.h> #include <X11/Xos.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/extensions/xf86vmode.h> #include <math.h> int main(int argc, char **argv) { /* XF86 substitution table */ uint16_t rtable[256]; /* read input */ uint32_t lowcut = atoi(argv[1]); uint32_t highcut = (255-atoi(argv[2])); float slope = 257; float range = 65535 - (lowcut*257 + highcut*257); printf("range = %f\n", range); if(range != 0) { slope *= 65535/range; } printf("slope = %f\n", slope); /* compute profile */ for(int i=0; i<256; i++) { rtable[i] = (uint16_t) (slope*(i-lowcut)); if(i<=lowcut) { rtable[i] = 0; } if(i>=255-highcut) { rtable[i] = 0xffff; } printf("%05i ", rtable[i]); if(i%16 == 15 && i>1) { printf("\n"); } } /* X11 magic */ Display *dpy = NULL; dpy = XOpenDisplay (NULL); int screen = DefaultScreen (dpy); XF86VidModeSetGammaRamp (dpy, screen, 256, rtable, rtable, rtable); }