Question

I'm using this code to generate a random UIColor for UILabel text in an ios app with a white background.

  • Problem is that some of the text turns out to be invisible against the white background.
  • How would you modify the code to ensure that any color chosen would be reasonably visible on a white background.

This question is as much about colors as it is programming.

+ (UIColor *) randomColor {
    CGFloat red =  (CGFloat)arc4random()/(CGFloat)RAND_MAX;
    CGFloat blue = (CGFloat)arc4random()/(CGFloat)RAND_MAX;
    CGFloat green = (CGFloat)arc4random()/(CGFloat)RAND_MAX;
    return [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
}
Was it helpful?

Solution

What I would do is determine the "gray" level of the RGB value. If it's "too close to white", then try again.

A formula I've used is:

float gray = 0.299 * red + 0.587 * green + 0.114 * blue;

This gives 0 for black and 1 for white. Pick a threshold such as 0.6 or whatever works for you.

+ (UIColor *) randomColor {
    while (1) {
        CGFloat red =  (CGFloat)arc4random()/(CGFloat)RAND_MAX;
        CGFloat blue = (CGFloat)arc4random()/(CGFloat)RAND_MAX;
        CGFloat green = (CGFloat)arc4random()/(CGFloat)RAND_MAX;
        CGFloat gray = 0.299 * red + 0.587 * green + 0.114 * blue;
        if (gray < 0.6) {
            return [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
        }
    }
}

OTHER TIPS

white is 1, 1,1. I think you can hack it so that as you generate colors you do multiple tries till you values are not to close to 1.0 1.0 1.0. really if one was .5 the rest were close to 1.0 your fine. statistically you should reach a color that meets the rules in a few tries. You would through inspection have to see what threshold is acceptable.

I think Maddy's answer is the best answer you've gotten.

Another, similar approach would be to calculate the Pythagorean distance between your color and the background color. Pseudocode, where the two colors are red1/green1/blue1 and red2/blue2/green2

CGFloat difference = sqrt( (red1 - red2)^2 + (green1 - green2)^2 + 
(blue1 - blue2)^2 );

That approach would let you find colors that are different from any arbitrary background color. To allow for human color perception, you could also use the weight values from Maddy's grayscale formula:

CGFloat difference = sqrt( 0.299 * (red1 - red2)^2 + 0.587 * (green1 - green2)^2 + 
0.114 * (blue1 - blue2)^2 );

Better still would be to convert the RGB values to LAB color space and compare the distance between colors in LAB space, but that's way beyond the scope of this discussion.

The (R,G,B) turns to white when the values are closer to 255, 255, 255. So, make your random number generator to not to generate too close numbers to 255 for any of these colors. Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top