3

Assume that I've a gray image, and I want to draw e.g. text on it. Now the image has some dark and some bright regions. So if I choose for every character a separate color, in what way do I compute such a color to gain highest contrast of the text?

A pragmatic approach is to use yellow. (I don't know why, but its often used for subtitles in movies and documentaries) Furthermore I could darken the yellow in regions of bright background, and highlight it in regions of dark background. But this may provide some layer-effects.

I know that the color space may be important. I start with an RGB gray value, but LAB, HSV, or HSL may be better suited to compute the optimal color.

EDIT: As there was the question for a useful use-case: I really do not want to paint letters of text in different color. It is about color choosing for particular glyphs on gray textured background. (E.g. an MR image.)

math
  • 8,514
  • 10
  • 53
  • 61
  • Not sure if it helps but check this post http://serennu.com/colour/rgbtohsl.php – Mikel Oct 22 '13 at 14:45
  • Thanks, but this uses the HSV model, and need a proper color *value* to switch it into opposite color. However when dealing with gray *colors*, the saturation is 0, hence the value may be ignored. – math Oct 22 '13 at 14:59
  • WCAG has a formula for determining the contrast ratio of two colours using their "relative luminance" (luminance within a colour space): http://www.w3.org/TR/WCAG20/#contrast-ratiodef - it doesn't tell you what the optimal colour is, but you could use this to "search" for the desired colour. – millimoose Oct 22 '13 at 22:08
  • That said, going by the notes in that link, your best bet would be using either a shadow or a border that contrasts with the fill of the letter. Either the fill colour will contrast with the background, or the border will contrast with the background, or the fill will contrast with the drop shadow, which makes things readable under most circumstances, without making the text multicoloured. (iOS 7 dropped this for the Springboard, and the end result is that you pretty much have to use nonbusy wallpapers.) – millimoose Oct 22 '13 at 22:11

1 Answers1

1

The simplest answer to your question is to maximize the distance between the background and your text color.

If you convert to HSL, you can do this by maximizing the distance between L (V in HSV). And all that requires is to select white when the background lightness is less than 50% and black otherwise. Here is an example: http://jsfiddle.net/E2kU4/

if(bgLightness < 50){
    color = "white";
}else{
    color = "black";   
}

I think that pretty much solves it, but on to a few other points:

I'm not sure what the use case is for this. A word with different colored characters might look really bad. Typically, subtitles select a single color for consistency.

Yellow does stand out against a black and white image because of its saturation. Furthermore (and I'm not sure how to put this into words exactly), yellow has a really high chroma compared to other colors with similar lightness. It is best demonstrated on the HUSL page; by the way, HUSL is a great library for creating readable colors.

Yellow easily contrasts with dark colors because it is very light. It doesn't contrast with light colors as well, but that is usually solved by adding a shadow/outline in subtitles. Another example: http://jsfiddle.net/E2kU4/1/

But you can apply the same technique (of applying a shadow or outline) to the black/white example for maximum contrast. Now, the outline has the maximal contrast against the text. The outline stands out from the background too, unless those colors are similar, in which case the contrast is already extremely high (e.g. Near black background, black outline, white text) http://jsfiddle.net/E2kU4/2/

Lastly, converting to and from HSL/RGB should be trivial. There are plenty of libraries to do it.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Jere
  • 3,377
  • 1
  • 21
  • 28
  • `L` in `HSL` and `V` in `HSV` are **awful** measures of perceptual brightness. E.g. `#0000FF` (lightest saturated blue), and `#FFFF00` (lightest saturated yellow) have the same "lightness", but clearly the yellow appears much lighter. – millimoose Oct 22 '13 at 22:04
  • Yup... I tried to say that and linked to a page that explained it in detail. I'm not sure how necessary it is to consider at all though because the stated problem requires contrasting with gray and, at least to me, seems rather trivial. – Jere Oct 22 '13 at 22:36
  • Thanks, I've edited the question to give a better use-case (thats what I am really interested in). Also the outlining of yellow letters will make them stand out, or on top, of the image. This is what I do not want for the glyphs. I want them in the same position as the background. Thanks for your explanation of the yellow color. This is really helpful. Can you say how to perform contrast maximization with yellow colors instead of white and black? – math Oct 23 '13 at 08:38
  • If the image is textured, you probably need to start by computing an average of the lightness of the surrounding grey pixels. The rest would involve using a color space like [LAB](http://en.wikipedia.org/wiki/Lab_color_space) that accounts for perceptual lightness and finding the maximum distance from that average background color. That's quite a bit more complex. It would be somewhat simplified by sticking to a yellow hue, but I'm fairly certain the resulting maximal contrasting could still be white or black (and brown of course). – Jere Oct 23 '13 at 13:40