Jump to content
  • Advertisement
Sign in to follow this  

Rounding to nearest color?

This topic is 3677 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How do you implement something like rounding to the nearest color, given a RGB value? There are clearly lots of cases if i wanted to use a bunch of if statements, is there a standard way to round to a given color(or a way in C#)? For instance, how do you know if a color is yellow, or red, etc.

Share this post


Link to post
Share on other sites
Advertisement
One way is to convert to HSV color space.
This gives you one color value (hue) as opposed to three. Look at the hue color spectrum and you can easily define boundaries for yellow, green etc.

Share this post


Link to post
Share on other sites
I'm not sure if this is technically correct, but it feels intuitive and works well in a program I wrote to convert an image to a paricular hard-coded palette.

The trick is to work out the "distance" between your colour and the possible matches, then to take the match that is the shortest distance away. To calculate the distance, I simply used Pythagoras's theorem. That is:
static int GetDistanceBetweenColours(Color a, Color b) {
int dR = a.R - b.R, dG = a.G - b.G, dB = a.B - b.B;
return dR * dR + dG * dG + dB * dB;
}

As we'll be just comparing the distances against other distances, you can ignore taking the square root (so this actually calculates the distance squared). You could then use it in a method like this:
static Color GetClosestColour(Color source, IEnumerable<Color> palette) {

// Store the current closest distance and colour:
int CurrentClosestDistance = int.MaxValue;
Color CurrentClosestColour = Color.Black;

// Iterate over the possible matches, and check the distance each time.
foreach (Color c in palette) {
int d = GetDistanceBetweenColours(source, c);
if (d < CurrentClosestDistance) {
CurrentClosestDistance = d;
CurrentClosestColour = c;
}
}

// Return the closest colour!
return CurrentClosestColour;
}

Share this post


Link to post
Share on other sites
I would suggest benryves method, except for determining the distance I would suggest weighting each channel by its perceptual significance (instead of straight Euclidean distance), just use the NTSC conversion weights which I think are {0.299, 0.587, 0.114}

Share this post


Link to post
Share on other sites
I've written a C# method to do this that finds the closest color match from an array of color swatches. Pretty much the same thing as benryves's solution.

private Color GetColorMatch(Color col)
{
Color ColorMatch = Color.Empty;

int LeastDistance = int.MaxValue;

int Alpha = col.A;
int Red = col.R;
int Green = col.G;
int Blue = col.B;

for(int i=0; i<SwatchArray.Length; i++)
{
Color PaletteColor = SwatchArray;

int AlphaDistance = PaletteColor.A - Alpha;
int RedDistance = PaletteColor.R - Red;
int GreenDistance = PaletteColor.G - Green;
int BlueDistance = PaletteColor.B - Blue;

int Distance = ( AlphaDistance * AlphaDistance ) +
( RedDistance * RedDistance ) +
( GreenDistance * GreenDistance ) +
( BlueDistance * BlueDistance );

if(Distance < LeastDistance)
{
ColorMatch = PaletteColor;
LeastDistance = Distance;

if(Distance == 0)
return PaletteColor;
}
}

return ColorMatch;
}


Share this post


Link to post
Share on other sites
Quote:
Original post by ginkeq
How do you implement something like rounding to the nearest color, given a RGB value?

There are clearly lots of cases if i wanted to use a bunch of if statements, is there a standard way to round to a given color(or a way in C#)?

For instance, how do you know if a color is yellow, or red, etc.


What is "a color" for the purpose of your rounding? Every RGB value describes a particular colour.

Anyway, to pick a "nearest" colour, you must also define the "distance" between two colours. There are a few different ways to do this.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!