Color contrast correction
I finally took some time to finish my color contrast corrector. It's now able to compare two colors and to tell if they are readable when used as foreground and background color for text rendering. I
I finally took some time to finish my color contrast corrector.
It’s now able to compare two colors and to tell if they are readable when used as foreground and background color for text rendering. If they are too close, the code corrects both colors so to they’ll become distant enough to be readable.
To do that, it uses color coordinates in the CIE L_a_b* colorspace. This allows to determine the luminance difference between 2 colors very easily by comparing the L component of the coordinates. The default threshold used to determine readability based on luminance difference is 40 (on 100), which seems to give pretty good results so far.
Then it uses the CIE Delta E 2000 formula to obtain the distance between colors. A distance of 6 is considered to be enough for the colors to be distinctive in our case, but that can be adjusted anyway. That depends on reader’s eyes.
If both the color and luminance distances are big enough, the color pair is considered readable when used upon each other.
If these criteria are not satisfied, the code simply tries to correct the color by adjusting the L (luminance) component of the colors so their difference is 40. Optionally, the background color can be fixed so only the foreground color would be adjusted; this is especially handy when the color background is not provided by any external style, but it the screen one (like the Emacs frame background in my case).
Here is an example result generated over 10 pairs of random colors. Left colors are randomly generated, and right colors are the corrected one.
| Original | Corrected | |
|---|---|---|
| DarkSeaGreen4 / gray67 | → | #4a6b4b / #cccccc |
| SlateGray4 / forest green | → | #9faec0 / #005700 |
| grey13 / grey36 | → | #131313 / #6c6c6c |
| MediumPurple2 / honeydew | → | #9e78ed / #f0fff0 |
| grey43 / chartreuse3 | → | #5e5e5e / #79de25 |
| linen / DeepPink2 | → | linen / DeepPink2 |
| CadetBlue4 / blue1 | → | #6c9fa4 / #0000e1 |
| gray33 / NavajoWhite3 | → | #525252 / #cfb58c |
| chartreuse1 / RosyBrown3 | → | #9cff38 / #b28282 |
| medium violet red / DeepPink1 | → | #9c0060 / #ff55b9 |
All this has been written in Emacs Lisp. The code is now available in Gnus (and therefore in Emacs 24) in the packages color-lab and shr-color.
A future work would be to add support for colour blindness.
As a side note, several people pointed me at the WCAG formulas to determine luminance and contrast ratio. These are probably good criteria to choose your color when designing a user interface. However, they are not enough to determine if displayed color will be readable. This means you can use them if you are a designer, but IMHO they are pretty weak for detecting and correcting colors you did not choose.
Related posts
The bad practice in FOSS projects management
During the OpenStack summit a few weeks ago, I had the chance to talk to some people about my experience on running open source projects. It turns out that after hanging out in communities and contrib
Read more →
Gnus notifications
Today, I've merged my Gnus notifications module inside Gnus git repository. This way, it will be available for everybody in Emacs 24.2.
Read more →