The two colors may not look close, but there are only 140 "named" colors out of 16,777,216 possible combinations (256 * 256 * 256).
It is difficult to look at the RGB values and make any conclusions regarding the color matching.
'GetNearest...
' http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/b2d491ac-4031-46d6-bccb-8bf9a46c2289
' http://www.eggheadcafe.com/conversation.aspx?messageid=31472401&threadid=31472286
Imports System.Drawing
Imports System.Reflection
Imports System.Runtime.CompilerServices
Namespace Drawing
<HideModuleName()> _
Public Module ColorExtensions
''' <summary>
''' Gets the <see cref="System.Drawing.Color.Name">System.Drawing.Color.Name</see> of the closest matching color.
''' </summary>
''' <example>
''' <code>
''' Private Sub Example()
''' Dim oColor As Color = Color.FromName(GetNearestName(Color.FromArgb(255, 255, 255, 0)))
''' Debug.Assert(oColor.Name = "Yellow")
''' End Sub
''' </code>
''' </example>
<Extension()> _
Public Function GetNearestName(ByVal unknownColor As Color) As String
'short-circut
If unknownColor.IsNamedColor Then
Return unknownColor.Name
End If
Dim oBestMatch As ColorName = GetNearestNameInternal(unknownColor)
Return oBestMatch.Name
End Function
''' <summary>
''' Gets the <see cref="System.Drawing.KnownColor">System.Drawing.KnownColor</see> of the closest matching known color.
''' </summary>
''' <example>
''' <code>
''' Private Sub Example()
''' Dim oColor As Color = Color.FromKnownColor(GetNearestKnownColor(Color.FromArgb(255, 255, 255, 0)))
''' Debug.Assert(oColor.Name = "Yellow")
''' End Sub
''' </code>
''' </example>
<Extension()> _
Public Function GetNearestKnownColor(ByVal unknownColor As Color) As KnownColor
'short-circut
If unknownColor.IsKnownColor Then
Return unknownColor.ToKnownColor
End If
Dim oBestMatch As ColorName = GetNearestKnownColorInternal(unknownColor)
Return oBestMatch.Color.ToKnownColor
End Function
<DebuggerDisplay("Name={Color.Name}, Distance={Distance}, ARGB=({Color.A}, {Color.R}, {Color.G}, {Color.B})")> _
Friend Structure ColorName
Public Name As String
Public Color As Color
Public Distance As Double
''' <summary>
''' Returns RGB=(212,208,200)
''' </summary>
Public Function ToRGBString() As String
Return String.Format("RGB=({0},{1},{2})", Color.R, Color.G, Color.B)
End Function
End Structure
Friend Function GetNearestNameInternal(ByVal unknownColor As Color) As ColorName
Dim oBestMatch As ColorName = Nothing
Dim nClosestDistance As Double = Double.MaxValue
Dim oBindingFlags As BindingFlags = _
BindingFlags.DeclaredOnly Or _
BindingFlags.Public Or _
BindingFlags.Static
For Each oProperty As PropertyInfo In GetType(Color).GetProperties(oBindingFlags)
Dim oNamedColor As Color = DirectCast(oProperty.GetValue(Nothing, Nothing), Color)
Dim nDistance As Double
nDistance = System.Math.Sqrt( _
(CInt(unknownColor.R) - oNamedColor.R) ^ 2 + _
(CInt(unknownColor.G) - oNamedColor.G) ^ 2 + _
(CInt(unknownColor.B) - oNamedColor.B) ^ 2)
nDistance = System.Math.Sqrt(nDistance / 3)
If nDistance < nClosestDistance Then
nClosestDistance = nDistance
oBestMatch.Name = oProperty.Name
oBestMatch.Distance = nDistance
oBestMatch.Color = oNamedColor
End If
Next
Return oBestMatch
End Function
Friend Function GetNearestKnownColorInternal(ByVal unknownColor As Color) As ColorName
Dim oBestMatch As ColorName = Nothing
Dim nClosestDistance As Double = Double.MaxValue
For Each sColorName As String In [Enum].GetNames(GetType(KnownColor))
Dim oNamedColor As Color = Color.FromName(sColorName)
Dim nDistance As Double
nDistance = System.Math.Sqrt( _
(CInt(unknownColor.R) - oNamedColor.R) ^ 2 + _
(CInt(unknownColor.G) - oNamedColor.G) ^ 2 + _
(CInt(unknownColor.B) - oNamedColor.B) ^ 2)
nDistance = System.Math.Sqrt(nDistance / 3)
If nDistance < nClosestDistance Then
nClosestDistance = nDistance
oBestMatch.Name = oNamedColor.Name
oBestMatch.Distance = nDistance
oBestMatch.Color = oNamedColor
End If
Next
Return oBestMatch
End Function
#Region " Conditional Testing for GetNearest... Methods "
<Conditional("DEBUG")> _
Friend Sub TestGetNearest()
'from immediate window
' ColorExtensions.Test
'
'Results based on "Windows XP" default theme, with the display name of "Windows XP style'.
'
'Windows XP style
' ActiveBorder, RGB=(212,208,200); LightGray, RGB=(211,211,211); ActiveBorder, RGB=(212,208,200)
' ActiveCaption, RGB=(0,84,227); RoyalBlue, RGB=(65,105,225); ActiveCaption, RGB=(0,84,227)
' ActiveCaptionText, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' AppWorkspace, RGB=(128,128,128); Gray, RGB=(128,128,128); AppWorkspace, RGB=(128,128,128)
' Control, RGB=(236,233,216); AntiqueWhite, RGB=(250,235,215); Control, RGB=(236,233,216)
' ControlDark, RGB=(172,168,153); DarkGray, RGB=(169,169,169); ControlDark, RGB=(172,168,153)
' ControlDarkDark, RGB=(113,111,100); DimGray, RGB=(105,105,105); ControlDarkDark, RGB=(113,111,100)
' ControlLight, RGB=(241,239,226); Beige, RGB=(245,245,220); ControlLight, RGB=(241,239,226)
' ControlLightLight, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' ControlText, RGB=(0,0,0); Black, RGB=(0,0,0); ControlText, RGB=(0,0,0)
' Desktop, RGB=(0,78,152); Teal, RGB=(0,128,128); Desktop, RGB=(0,78,152)
' GrayText, RGB=(172,168,153); DarkGray, RGB=(169,169,169); ControlDark, RGB=(172,168,153)
' Highlight, RGB=(49,106,197); RoyalBlue, RGB=(65,105,225); Highlight, RGB=(49,106,197)
' HighlightText, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' HotTrack, RGB=(0,0,128); Navy, RGB=(0,0,128); HotTrack, RGB=(0,0,128)
' InactiveBorder, RGB=(212,208,200); LightGray, RGB=(211,211,211); ActiveBorder, RGB=(212,208,200)
' InactiveCaption, RGB=(122,150,223); CornflowerBlue, RGB=(100,149,237); InactiveCaption, RGB=(122,150,223)
' InactiveCaptionText, RGB=(216,228,248); Lavender, RGB=(230,230,250); InactiveCaptionText, RGB=(216,228,248)
' Info, RGB=(255,255,225); LightYellow, RGB=(255,255,224); Info, RGB=(255,255,225)
' InfoText, RGB=(0,0,0); Black, RGB=(0,0,0); ControlText, RGB=(0,0,0)
' Menu, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' MenuText, RGB=(0,0,0); Black, RGB=(0,0,0); ControlText, RGB=(0,0,0)
' ScrollBar, RGB=(212,208,200); LightGray, RGB=(211,211,211); ActiveBorder, RGB=(212,208,200)
' Window, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' WindowFrame, RGB=(0,0,0); Black, RGB=(0,0,0); ControlText, RGB=(0,0,0)
' WindowText, RGB=(0,0,0); Black, RGB=(0,0,0); ControlText, RGB=(0,0,0)
' Transparent, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' Black, RGB=(0,0,0); Black, RGB=(0,0,0); ControlText, RGB=(0,0,0)
' Gray, RGB=(128,128,128); Gray, RGB=(128,128,128); AppWorkspace, RGB=(128,128,128)
' Navy, RGB=(0,0,128); Navy, RGB=(0,0,128); HotTrack, RGB=(0,0,128)
' White, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' ButtonFace, RGB=(236,233,216); AntiqueWhite, RGB=(250,235,215); Control, RGB=(236,233,216)
' ButtonHighlight, RGB=(255,255,255); Transparent, RGB=(255,255,255); ActiveCaptionText, RGB=(255,255,255)
' ButtonShadow, RGB=(172,168,153); DarkGray, RGB=(169,169,169); ControlDark, RGB=(172,168,153)
' GradientActiveCaption, RGB=(61,149,255); DodgerBlue, RGB=(30,144,255); GradientActiveCaption, RGB=(61,149,255)
' GradientInactiveCaption, RGB=(157,185,235); LightSteelBlue, RGB=(176,196,222); GradientInactiveCaption, RGB=(157,185,235)
' MenuBar, RGB=(236,233,216); AntiqueWhite, RGB=(250,235,215); Control, RGB=(236,233,216)
' MenuHighlight, RGB=(49,106,197); RoyalBlue, RGB=(65,105,225); Highlight, RGB=(49,106,197)
'
Debug.WriteLine(System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName)
For Each sKnownColorName As String In [Enum].GetNames(GetType(KnownColor))
Dim oBaseColor As New ColorName
oBaseColor.Name = sKnownColorName
oBaseColor.Color = Color.FromName(sKnownColorName)
Dim oTestColor As Color = Color.FromArgb(255, oBaseColor.Color.R, oBaseColor.Color.G, oBaseColor.Color.B)
Dim oNearestNamed As ColorName = GetNearestNameInternal(oTestColor)
Dim oNearestKnown As ColorName = GetNearestKnownColorInternal(oTestColor)
'results will vary due to the current display theme properties
If oNearestNamed.Name <> oNearestKnown.Name Then
Debug.Write("' ")
Debug.Write(oBaseColor.Name)
Debug.Write(", ")
Debug.Write(oBaseColor.ToRGBString)
Debug.Write("; ")
Debug.Write(oNearestNamed.Name)
Debug.Write(", ")
Debug.Write(oNearestNamed.ToRGBString)
Debug.Write("; ")
Debug.Write(oNearestKnown.Name)
Debug.Write(", ")
Debug.Write(oNearestKnown.ToRGBString)
Debug.WriteLine("")
End If
Next
End Sub
''' <summary>
''' Dump all the Is... Properties
''' <example>
''' Current ActiveBorder is (255, 212, 208, 200)
''' Color.FromArgb(255, 212, 208, 200) 'ActiveBorder
''' Color.FromName("Yellow") '255, 255, 0
''' Color.FromArgb(255, 255, 255, 0) 'Yellow
''' </example>
''' </summary>
<Extension()> _
<Conditional("DEBUG")> _
Friend Sub BreakOnIsProperties(ByVal color As Color)
Dim I As Color = color.FromArgb(color.A, color.R, color.G, color.B)
If I.IsEmpty Then
Stop
End If
If I.IsKnownColor Then
Stop
End If
If I.IsNamedColor Then
Stop
End If
If I.IsSystemColor Then
Stop
End If
End Sub
#End Region
End Module
End Namespace