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
Posted in VB.NET and Windows on January 20th