This shows you the differences between two versions of the page.
— |
contrast [2017-05-25 01:54:20] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Setting contrast in X.org ====== | ||
+ | Use-case: Enhance contrast when reading scanned document and document viewer does not support contrast adjustment. | ||
+ | |||
+ | <note warning>XF86VidModeSetGammaRamp [[https://bugs.freedesktop.org/show_bug.cgi?id=27222#c27|is broken]] in recent X.org. I have created an [[https://jenda.hrach.eu/f/xlevels/redshift.d51c25e76eaf9d7f9318f5ec1b4e7eb04454f46c.patch|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: | ||
+ | <code>./xlevels white_threshold black_treshold</code> | ||
+ | (it's the same syntax like in GIMP) | ||
+ | |||
+ | Examples: | ||
+ | |||
+ | * Web2.0 page using gray text on white background (like [[http://blog.cryptographyengineering.com/|this one]]) (very common, no idea why designers do this, and Firefox can't cope with this): | ||
+ | <code>./xlevels 100 255</code> | ||
+ | |||
+ | * Scanned or photographed document | ||
+ | <code>./xlevels 50 230</code> | ||
+ | |||
+ | * Help! I've broken my X server and I see only a white/black screen! | ||
+ | <code>xcalib -c</code> | ||
+ | |||
+ | |||
+ | <code>#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); | ||
+ | |||
+ | } | ||
+ | |||
+ | </code> |