Reputation: 583
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?
Upvotes: 1
Views: 7147
Reputation: 6445
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
Upvotes: -1
Reputation: 13055
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/
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.
Upvotes: 5
Reputation: 318774
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
}
Upvotes: 4
Reputation: 8163
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);
Upvotes: 3