1

Given a huge list of RGB values, I would like to associate and pair them to a standard UIColor. For example, (255,0,0) is the "common" Red color. I would like to pair and label values like (254,85,44) and (193,0,1) as "Red" as well. As long as they are close to a shade of red I would like to say it is "red". What would be the best way to accomplish this? I tried testing for luminance and even comparing it to the standard (255,0,0) for a generic formula but was unsuccessful. Any suggestions?

8
  • I don't think we can decide for you, what you consider "red". You could probably set some criteria based on the ratio of say r/g and r/b, and if those ratios are high enough, call it red. But you'll have to experiment to see what criteria meet your needs. Commented May 15, 2013 at 21:15
  • @rdelmar I know this is all subjective but I guess anything that is pretty close to "Red" will do? Maybe the strongest rgb color component that stands out of the three will classify it as Red? Commented May 15, 2013 at 21:19
  • Do you need to do this for all of the standard named UIColor values or just "red"? Commented May 15, 2013 at 21:36
  • You can get the hue, saturation, brightness, and alpha values of your colors (with getHue:saturation:brightness:alpha:), and see if the hue is close enough to 0 (or 1, red is at both ends of the scale) and the brightness is above a certain threshold. That would be the easiest way, I think. Commented May 15, 2013 at 21:41
  • @rdelmar Does the getHue:... method work on a UIColor created with RGB? Commented May 15, 2013 at 21:44

4 Answers 4

5

Basically the same as what @frowing said, but I have a few more #defined macros that make my life easier:

#define RGB(R, G, B) ([UIColor colorWithRed:R/255.0f green:G/255.0f blue:B/255.0f alpha:1.0f]) #define G(W) ([UIColor colorWithWhite:W/255.0f alpha:1.0f]) #define RGBA(R, G, B, A) ([UIColor colorWithRed:R/255.0f green:G/255.0f blue:B/255.0f alpha:A]) #define GA(W, A) ([UIColor colorWithWhite:W/255.0f alpha:A]) #define RANDCOLOR ([UIColor colorWithHue:fmodf(((float)arc4random()/0x100000000)+0.618033988749895f, 1.0f) saturation:0.75f brightness:0.95f alpha:1.0f]) // From http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/ #define RANDCOLOR_ALPHA(A) ([UIColor colorWithHue:fmodf(((float)arc4random()/0x100000000)+0.618033988749895f, 1.0f) saturation:0.75f brightness:0.95f alpha:A]) // From http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/ 
  • RGB(R, G, B) is for a simple RGB to UIColor conversion
  • G(W) is for a simple UIColor in the gray colorspace
  • RGBA(R, G, B, A) is same as RGB() but with a specified alpha channel
  • GA(W, A) is same as G() but with a specified alpha channel
  • RANDCOLOR() is just a random color (see link for more details on why this isn't just a random number for each RGB value)
  • RANDCOLOR_ALPHA(A) is same as RANDCOLOR() but with a specified alpha channel

Edit 1: I read your question wrong. My fault.

I would start off with a set of defined colors that you want to use as your labels. For example:

#define COLOR_RED RGB(193.0f, 0.0f, 1.0f) 

Then I would use an rgb to rgb calculation to figure out how far the colors are in 3d space. So something like:

const float* rgb1 = CGColorGetComponents( color1.CGColor ); const float* rgb2 = CGColorGetComponents( color2.CGColor ); double diff = pow(pow(rgb2[0] - rgb1[0], 2) + pow(rgb2[1] - rgb1[1], 2) + pow(rgb2[2] - rgb1[2], 2), 0.5); 

Pick a threshold for the resultant, write this into a function, iterate over your labels (or arrays of labels and corresponding UIColors), and return the label where the diff is under a certain threshold.

One thing to note, this is assuming your colors are all in the RGB colorspace. CGColorGetComponents will return RGB only when your color is in the RGB colorspace. A grayscale color will return different values (and a different size array for rgb1 and rgb2).

Edit 2: Ok, I did some research from my old textbooks and the color data you want to be using is called L*a*b color space.

From http://en.wikipedia.org/wiki/Lab_color_space

Unlike the RGB and CMYK color models, Lab color is designed to approximate human vision.

I would first convert the RGB values into L*a*b space, then use the l,a,b values in the same 3d space distance calculation I have outlined above for the rgb values. This is known as the CIE76 algorithm (it's not the best, but probably one of the easier ones to implement... see my note below). That numeric difference value should get you close to understanding how similar two colors are to the human eye. Then based on some tests, I would pick a threshold value that you're comfortable with.

For converting RGB to L*a*b I found this page: http://cookbooks.adobe.com/post_Useful_color_equations__RGB_to_LAB_converter-14227.html

NOTE: This is basically the quickest (albeit, a bit dirty) way to get to color difference. I say dirty because there are more sophisticated algorithms out there that doesn't get distorted at the more saturated end of the color spectrum. If you want to see the more up-to-date algorithms, take a look at this wikipedia: http://en.wikipedia.org/wiki/Color_difference.

Sign up to request clarification or add additional context in comments.

2 Comments

So if I do RGB(192,0,0) will that give me "Red"? Also, how should I go about the conversion from UIColor to a NSString?
This answer really has nothing to do with the question.
4

Your best bet is to convert the RBG value to HSL or HSV (sometimes referred to as HSB). Then check the hue value. If the hue comes out in the range 0-15 or 340-360 (adjust these ranges to suit your own definition of "red"), then you could consider the color to be red. Of course some of these will be nearly black or white to you may also want to limit the luminance or brightness values as well.

int red = ... // your red value (0 - 255) int green = ... // your green value (0 - 255) int blue = ... // your blue value (0 - 255) UIColor *RGBColor = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:1.0]; CGFloat hue, saturation, brightness; if ([RGBColor getHue:&hue saturation:&saturation brightness:&brightness alpha:nil]) { // Replace 15 and 240 with values you consider to be "red" if (hue < 15/360.0 || hue > 240/360.0) { // this can be considered "red" } } else { // oops - can't convert } 

5 Comments

If I may ask, why is it division over 360.0?
@David, It's divided by 360 because hue, in this method, is measured in degrees (of a circle). Because it's a circle (like the color picker that you can bring up), one color (that happens to be red) is at both 0 and 360 degrees. The other two primary colors, green and blue, are at 120 and 240 degrees respectively.
Of course you may ask. The hue value is in degrees. So the 0.0 - 1.0 are converted to 0 - 360 for this code.
Got it, thanks! Now since Red is on both ends of the scale, that would mean it's close to 0 and 1 correct? Wouldn't I have to check for Saturation and Brightness to determine what kind of shade of red?
Yes, red is close to 0 and close to 1. And yes, looking at the saturation and brightness will indicate the kind of red. A 0 brightness is black regardless of all other values. A 0 saturation is some level of grey regardless of the other values. A saturation below some threshold, say 0.7, might be considered pink. Much of this is subjective.
3

If you want to convert RGB to UIColor, you can make use of this two inline functions:

#define RGB(r, g, b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1] #define RGBA(r, g, b, a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a] 

And then use them like this:

UIColor *color = RGB(100,100,100); 

2 Comments

This answer really has nothing to do with the question.
Actually his code works perfect and answers the question. School yourself before declaring someone incorrect.
-1

Create category for UIColor+RGB.

in .h

#import <UIKit/UIKit.h> @interface UIColor (RGB) +(UIColor *)colorWithRedInt:(NSInteger)red greenInt:(NSInteger)green blueInt:(NSInteger)blue alpha:(CGFloat)alpha; +(UIColor *)commonTextColor; +(UIColor *)tabBarColor; @end 

in.m

#import "UIColor+RGB.h" @implementation UIColor (NormalizedRGB) +(UIColor *)colorWithRedInt:(NSInteger)red greenInt:(NSInteger)green blueInt:(NSInteger)blue alpha:(CGFloat)alpha { return [self colorWithRed:red/256.0 green:green/256.0 blue:blue/256.0 alpha:1.0]; } @end 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.