tags:

views:

493

answers:

5

I'm looking for a function that can accurately represent the distance between two colours as a number or something.

For example I am looking to have an array of HEX values or RGB arrays and I want to find the most similar colour in the array for a given colour

eg. I pass a function a RGB value and the 'closest' colour in the array is returned

+8  A: 

Each color is represented as a tuple in the hex code. To determine close matches you need need to subtract each RGB component seperatly.

Example:

Color 1: #112233 
Color 2: #122334
Color 3: #000000

Difference Between color1 and color2: R=1,  G=1   B=1  = 0x3 
Difference Between color3 and color1: R=11, G=22, B=33 = 0x66

So color 1 and color 2 are closer than
1 and 3.

edit

So you want the closest named color? Create an array with the hex values of each color, iterate it and return the name. Something like this;

function getColor($rgb)
{
 // these are not the actual rgb values
 $colors = array(BLUE =>0xFFEEBB, RED => 0x103ABD, GREEN => 0x123456);

 $largestDiff = 0;
 $closestColor = "";
 foreach ($colors as $name => $rgbColor)
 {
  if (colorDiff($rgbColor,$rgb) > $largestDiff)
  {
   $largestDiff = colorDiff($rgbColor,$rgb);
   $closestColor = $name;
  }

 }
 return $closestColor;

}

function colorDiff($rgb1,$rgb2)
{
 // do the math on each tuple
 // could use bitwise operates more efeceintly but just do strings for now.
 $red1 = hexdec(substr($rgb1,0,2));
 $green1 = hexdec(substr($rgb1,2,2));
 $blue1 = hexdec(substr($rgb1,4,2));

 $red2 = hexdec(substr($rgb2,0,2));
 $green2 = hexdec(substr($rgb2,2,2));
 $blue2 = hexdec(substr($rgb2,4,2));

 return abs($red1 - $red2) + abs($rgreen1 - $green2) + abs($blue2 - $blue2) ;

}
Byron Whitlock
I understand I need to get the RGB values, but im looking for a function that for can return the "most similar" color in an array for a given color.A simple example:[BLUE , RED, DARKRED, GREEN]If the function was given the color LIGHTBLUE, from the array above, Id expect the function to return "BLUE"CheersPhilip
Phil
If you aren't suing hex values at all, just create a function with a big switch statement that takes the color name and just returns what you think is the closest color name.
Byron Whitlock
The colofDiff function is good, but has to fix a bug in return, "return abs($red1 - $red2) + abs($green1 - $green2) + abs($blue1 - $blue2) ;"
Cesar
excellent! thank you
Phil
+3  A: 

A very simple approach is to calculate the summarized distance among the three dimensions. For example simple_distance("12,10,255","10,10,250")=7

A more sophisticated approach would be to take the square of the distances for each components and sum those - this way components being too far would be "punished" more: square_distance("12,10,255","10,10,250")=1*1+0*0+5*5=26.

Of course you would have to iterate over the list of colors and find the closest one.

Gergely Orosz
+2  A: 

you can convert your RGB value to HSL or HSV. then the colors are easy to compare: order colors by hue first, then by saturation, then by luminance. in the resulting order, 2 colors next to each other will appear as being very close perceptually.

beware that hue wraps around: for a hue ranging from 0 to 255, a hue of 0 and a hue of 255 are very close.

see the wikipedia article on HSL http://en.wikipedia.org/wiki/HSL_and_HSV for the formula which will allow you to convert RGB to HSL

(note that other color spaces, like L.a.b., may give better results, but conversion is more complicated)

Adrien Plisson
+4  A: 

Here is a paper on the subject which should give a good answer.

I was thinking that converting to HSL/HSV first would be a good idea also, but then I realized that at extreme values of S & L/V, H doesn't matter, and in the middle, it matters most.

I think if you want a simple solution, staying in the RGB space would be wiser. I'd use cartesian distance. If you're considering color R G B against Ri Gi Bi for several i, you want the i that minimizes

(R - Ri)^2 + (G - Gi)^2 + (B - Bi)^2
Grumdrig
+2  A: 

First you have to choose th appropriate color space you want the color comparisons to occur in (RGB, HSV, HSL, CMYK, etc.).

Assuming you want to know how close two points in the 3-dimenionsal RGB space are to each other, you can calculate the Pythagorean distance between them, i.e.,

d2 = (r1 - r2)**2 + (g1 - g2)**2 + (b1 - b2)**2;

This actually gives you the square of the distance. (Taking the square root is not necessary if you're comparing only the squared values.)

This assumes that you want to treat the R, G, and B values equally. If you'd rather weight the individual color components, such as what happens when you convert RGB into grayscale, you have to add a coefficient to each term of the distance, i.e.,

d2 = 30*(r1-r2)**2 + 59*(g1-g2)**2 + 11*(b1-b2)**2;

This assumes the popular conversion from RGB to grayscale of 30% red + 59% green + 11% blue.

Update

That last equation should probably be

d2 = (30*(r1-r2))**2 + (59*(g1-g2))**2 + (11*(b1-b2))**2;
Loadmaster