Author Topic: Finding closest matching RGB value from array  (Read 1000 times)

Let's say I have an RGB value, "231 56 24", and have an array with many different RGB values.

I need to find a color on that array which is the most similar to "231 56 24". How would I go about doing this? Apparently Blockland uses a similar method to load bricks with similar colors when using a different colorset.

Help would be much appreciated.

The cheapest way is finding the value with the lowest vectorDist(color1, color2), but of course, that can yield some strange color matches once in a while.

The cheapest way is finding the value with the lowest vectorDist(color1, color2), but of course, that can yield some strange color matches once in a while.
No yeah I've already tried that method, I need a method that will never fail at all. It needs to be completely accurate.

Grab the absolute values of r1 - r2, g1 - g2, and b1 - b2. Add together the absolute values. The set with the smallest added number is the closest to rgb1. (Note that I'm using r1, g1, etc only for examples sake; I know that's not how your variables work, being complete rgb values.)

Grab the absolute values of r1 - r2, g1 - g2, and b1 - b2. Add together the absolute values. The set with the smallest added number is the closest to rgb1. (Note that I'm using r1, g1, etc only for examples sake; I know that's not how your variables work, being complete rgb values.)
Yeah I did already try your method. The issue with it is that it doesn't take into consideration which values are higher in RGB.

By this i mean, let's say, you have 3 RGB values in the array. The first is "255 0 0", second is "0 255 0" and third is "0 0 255".
Let's pretend the value I want to match is "85 85 85", the script will automatically assume that either of the 3 in the array is identical, when really they are not.

One thing you could try is converting it to HSV/HSL and then do the same vectorDist method. It'd work at least a bit better than when using RGB.

One thing you could try is converting it to HSV/HSL and then do the same vectorDist method. It'd work at least a bit better than when using RGB.
I guess so, it would be the best bet at this moment.

Does anyone know how Badspot does it though? It works wonderfully for blockland.

I guess so, it would be the best bet at this moment.

Does anyone know how Badspot does it though? It works wonderfully for blockland.
build bot has a "findClosestColor"

http://forum.blockland.us/index.php?topic=219699.0
Link to thread you could have looked up

Code: (Client side) [Select]
function findclosestcolor(%x) //input four numbers between 0 and 1
{
for(%a=0; %a<64; %a++)
{
%match = mabs(getword(getcoloridtable(%a),0) - getword(%x,0)) + mabs(getword(getcoloridtable(%a),1) - getword(%x,1)) + mabs(getword(getcoloridtable(%a),2) - getword(%x,2)) + mabs(getword(getcoloridtable(%a),3) - getword(%x,3))*4;

if(%match < %bestmatch || %bestmatch $= "")
{
%bestmatch = %match;
%bestid = %a;
}
}
return %bestid; //trans may be messed up if you input a nearly-but-not-quite opaque color
}
Code: (Server Side) [Select]
getclosestpaintcolor(vectorscale(%rgb,255))

You could rate them on an exponential curve from the proper color. I don't know what the results would actually look like but in theory it should be better than vectorDist.

Code: [Select]
function colorMatch(%colorList, %color)
{
for(%i = 0; %i < getFieldCount(%colorList); %i++)
{
%testColor = getField(%colorList, %i);
%rDiff = mPow(mAbs(getWord(%testColor, 0) - getWord(%color, 0)),1.2);
%gDiff = mPow(mAbs(getWord(%testColor, 1) - getWord(%color, 1)),1.2);
%bDiff = mPow(mAbs(getWord(%testColor, 2) - getWord(%color, 2)),1.2);
%totalDiff = %rDiff + %gDiff + %bDiff;
if(%totalDiff < %lowestDiff || %lowestDiff $= "")
{
%lowestDiff = %totalDiff;
%lowestColor = %testColor;
}
}
return %lowestColor;
}

The exponential factor should make it throw out colors that are too different on any combination of axes.

I think Port's suggestion of converting to HSV and doing the vectorDist on them would return the closest matches.