April 4, 2007

ChangeLog: libcontrast fixes text color automatically

Author: Nathan Willis

David Trowbridge's new project libcontrast does exactly one thing: it makes color text readable, regardless of the background behind it. This solves a problem that confronts users in several specific contexts -- IRC, terminal emulators, and certain IM protocols, for example -- where text color is specified by a simple name like "red" or "dark green" instead of a precise RGB value. In those cases, the background color of the window may make the text unreadable.

The old-fashioned response to a named color was to render a hard-coded, specific RGB value, like #FF0000 for "red." But that #FF0000 text is not only invisible against a #FF0000 background, it is unreadable against anything in the neighborhood of #FF0000, and too intense to be clearly read against all sorts of other bright, saturated background colors.

Trowbridge hit upon a solution back in June that hinges on recognizing that "red" describes a broad chunk of the color space rather than one specific color. All an application is required to do is find some red that works. In that sense, you can exploit the ambiguity of the named color. Knowing the background color, you pick the best possible shade of red to maximize readability -- dark red on a light background, lighter red on a dark background.

Simply put, the algorithm starts by examining the background, then for the named text color it picks a foreground color as far away from the background as possible, while still within the acceptable range of meaning for "red" -- or whatever the named color is. It does this by making its calculations in the abstract CIE L*a*b* color space, even using special logic to handle odd cases where the background and foreground colors are almost the same.

You can see the results of Trowbridge's work on both his original blog entry and the updated follow-up. The examples on those two pages represent the outcome of his initial experiments; with hand-tweaking, the returns could be even greater.

Trowbridge added the functionality to XChat-GNOME, and submitted a patch to add the functionality to GTK+. When it became clear that the GTK+ patch was far from the front of the queue for acceptance, he decided instead to build it into a standalone library.

There will always be pathological cases that no technique can massage into readable text (e.g., HTML-formatted messages where both foreground and background colors are specified). For most other scenarios, though, the libcontrast technique can make semantically specified colors both meaningful and usable. Who would have thought there was a way to read black-on-black text?