Finding the Nearest Known Color

I recently ran across an interesting question in a usenet post; How do you convert an arbitrary color to a known / system color?

After some thought, I reasoned: in order to find the nearest known color, you must get the difference for each known color based on your sampled color. You could do this by looping through each known color in the enumeration Drawing.KnownColor.

Next, you could compare the R, G, and B values (or H, S, V values if that is more appropriate) for the known to the sample. To get the distance, you could either do a simple sum of the absolute differences, or if you are a Man or Woman of science, you would use the RMS (Root Mean Square) value. Finally, you keep the value with the smallest difference and return it.

In my sample code below, I also created a structure for returning the Name, Color and the Distance – this is just a little sugar to help the medicine go down, not really necessary.

Private R As New Random

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click

Dim randColor As Color = _
Color.FromArgb(R.Next(0, 255), _
R.Next(0, 255), _
R.Next(0, 255))

Me.RandomColorBox.BackColor = randColor
Me.RandomColorLabel.Text = randColor.ToString

'// now match to nearest known color
Dim nearest As ColorName = FindNearestKnown(randColor)
Me.KnownColorLabel.Text = nearest.Name
Me.NearestColorBox.BackColor = nearest.Color

End Sub

Structure ColorName
Public Color As Color
Public Name As String
Public Distance As Integer
End Structure

Public Function FindNearestKnown(ByVal c As Color) _
As ColorName
Dim best As ColorName

best.Name = Nothing

For Each colorName As String In _
[Enum].GetNames(GetType(KnownColor))
Dim known As Color = Color.FromName(colorName)
Dim dist As Integer

dist = Math.Abs(CInt(c.R) - known.R) _
+ Math.Abs(CInt(c.G) - known.G) _
+ Math.Abs(CInt(c.B) - known.B)

If best.Name Is Nothing _
OrElse dist < best.Distance Then
best.Color = known
best.Name = colorName
best.Distance = dist
End If
Next

Return best
End Function

Tagged Tags: , on January 20, 2008 at 10:49 pm