Rounding to nearest color?

Started by
4 comments, last by Zahlman 16 years ago
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.
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.
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;}

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

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}
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;}
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.

This topic is closed to new replies.

Advertisement