Recent Activity

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

Posted in VB.NET and Windows on January 20th