TfGuy44 wrote on Jan 21st, 2010, 4:07pm: return( map( dist_colors(cA,cB), 0, 441.67294, 0, 10 ) );
} // 441.67294 = dist(0,0,0,255,255,255)
sqrt(255*255*3) comes out as 441.67295593006... using Microsoft Calculator ("calc" on Windows), so I should expect the rounded dist() result to be 441.67296 (not that this will make much difference, mind you!).
Moving on...
This "distance" is the
Euclidean distance, and my suggestion is that this isn't the most appropriate measure in this case.
I suggest using the sum of the differences of each colour channel. Differs only one of red, green or blue: max distance is 255 (with score of 6.67). Differs in two of red, green and blue: max distance is 255*2=510 (with score of 3.33). Differs in all three red, green and blue: max distance is 255*3=765 (with score of 0). This is the so-called "
Manhattan distance" ("taxicab distance"), or rectilinear distance.
Warning: following code untested!
Code:float scoreRGB = map( abs(test.red()-ideal.red()) + abs(test.green()-ideal.green()) + abs(test.blue()-ideal.blue()), 0, 255*3, 10, 0 ); // Note score goes down to 0 as distance goes up
You might further decide that taking some measure of "RGB distance" isn't really what you want. Maybe other qualities of the colour are more important. Perhaps it would produce a more meaningful score based on the HSB colour model - hue, saturation, brightness - and perhaps you might weight those properties differently, eg score affected more by change in hue than by change in saturation. You will have to watch out for the "hue" wrapping around though!
Warning: following code untested!
Code:float MIN_SCORE = 0;
float MAX_SCORE = 10;
float r[] = { 360, 100, 100 }; // H,S,B ranges
float m[] = { 180, 100, 100 }; // max distances
float w[] = { 2, 1, 1 }; // weights
colorMode(HSB, r[0], r[1], r[2]);
float d[] = new float[3]; // H,S,B differences
// Max hue difference is "half-way around", after which
// the hue gets closer again
d[0] = abs(test.hue() - ideal.hue());
if (d[0] > m[0]) d[0] = r[0] - d[0];
d[1] = abs(test.saturation() - ideal.saturation());
d[2] = abs(test.brightness() - ideal.brightness());
float sum = 0;
float weightDivisor = 0;
for (int i = 0; i < d.length; i++)
{
sum += d[i] / m[i] * w[i]; // Normalise and weight
weightDivisor += w[i];
}
float weightedDistance = sum / weightDivisor;
// Note: score goes down as distance goes up
float score = map(weightedDistance, 0, 1, MAX_SCORE, MIN_SCORE );
Unfortunately, almost nothing worthwhile is easy, and the above code (or something like it) would need to be augmented to handle special cases: the HSB model has some degenerate values, such as when brightness is zero (in which case hue and saturation have no meaning nor effect), or saturation is zero (in which case hue doesn't have any meaning).
-spxl