I am using the Microsoft Cognitive Services / Vision API in my application.
Vision API returns colours as string - either HEX (without the "#" prefix), or as a Name.
In order to convert this to a System.Drawing.Color that I can use as a panel background color, I am using the below code:
// Hex Color Format
Regex hex = new Regex("^#(?:[0-9a-fA-F]{3}){1,2}$");
// Colours
System.Drawing.Color accent = new System.Drawing.Color();
System.Drawing.Color fore = new System.Drawing.Color();
System.Drawing.Color back = new System.Drawing.Color();
try
{
if (hex.IsMatch("#" + result.Color.AccentColor.ToString())) accent = ColorTranslator.FromHtml("#" + result.Color.AccentColor.ToString());
else accent = ColorTranslator.FromHtml(result.Color.AccentColor.ToString());
fore = ColorTranslator.FromHtml(result.Color.DominantColorForeground.ToString());
back = ColorTranslator.FromHtml(result.Color.DominantColorBackground.ToString());
displayData.Colors = new System.Drawing.Color[] { accent, fore, back };
}
catch (Exception e)
{
throw new Exception(e.Message.ToString());
}
This has worked fine in 99% of cases, however, when one of the Colors returns from Micrsoft Vision API with "Grey", I get an Exception:
Grey is not a valid value for Int32
(This is the only color name I've encountered but I don't know if there would be others)
From my understanding, this would be because "Grey" is not a HTML Color Name, as it should be "Gray" ("Grey" being the CSS name) http://www.rapidtables.com/web/color/gray-color.htm
What would be the best way to handle this Exception? I was thinking creating a Dictionary of "bad" color names and manually assign those colors their true HTML Color Name (or a System.Drawing.Color directly), but this seems prone to human error and a constant game of update the Color.
Thoughts? Thanks.
I probably did this is in a convoluted manner, but I merged all of your responses into one and I think it was a neat solution:
I create a new class called ColorFix
, which checks for "bad" names in a Dictionary<string, string>
(manually defined), then checks if it is a KnownName
, before otherwise just returning a new blank Color
object.
Then, from the calling class, I created a Method ColorFromString
which accepts the raw string color from the Microsoft API.
This is the old code that tries to ColorTranslate.FromHtml
-- and catches Exceptions -- except now Exceptions are processed through ColorFix
.
So round-about way of just parsing through a Dictionary and Checking if it's a KnownName.
I'm relatively new to C#, so here is my code if this helps anyone:
Controller.cs
// Colours
System.Drawing.Color accent = new System.Drawing.Color();
System.Drawing.Color fore = new System.Drawing.Color();
System.Drawing.Color back = new System.Drawing.Color();
try
{
accent = ColorFromString(result.Color.AccentColor.ToString());
fore = ColorFromString(result.Color.DominantColorForeground.ToString());
back = ColorFromString(result.Color.DominantColorBackground.ToString());
displayData.Colors = new System.Drawing.Color[] { accent, fore, back };
}
catch (Exception e)
{
throw new Exception(e.Message.ToString());
}
...
private System.Drawing.Color ColorFromString(string color)
{
System.Drawing.Color value = new System.Drawing.Color();
// Hex Color Format
Regex hex = new Regex("^#(?:[0-9a-fA-F]{3}){1,2}$");
try
{
if (hex.IsMatch("#" + color)) value = ColorTranslator.FromHtml("#" + color);
else value = ColorTranslator.FromHtml(color);
}
catch (Exception)
{
ColorFix colorFix = new ColorFix(color);
value = colorFix.Fix();
}
return value;
}
ColorFix.cs
using System;
using System.Collections.Generic;
using System.Drawing;
namespace Project.Services
{
class ColorFix
{
private string color;
public Dictionary<string, string> badColors = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
//
// Constructor, takes Color String
//
// @param string(color)
// @return void
//
public ColorFix(string color)
{
this.color = color;
badColors.Add("Grey", "Gray");
}
//
// Fix the Color Exception
//
// @return Color
//
public Color Fix()
{
if (Bad() != null) return (Color)Bad();
if (Known() != null) return (Color)Known();
return new Color();
}
//
// Check if Color is a system KnownColor
//
// @return Nullable<Color>
//
private Color? Known()
{
string colorLower = color.ToLower();
Array colorValues = Enum.GetValues(typeof(KnownColor));
string[] colorNames = Enum.GetNames(typeof(KnownColor));
for (int c = 0; c < colorValues.Length; c++)
{
if (colorNames.Equals(colorLower)) return Color.FromKnownColor((KnownColor)colorValues.GetValue(c));
}
return null;
}
//
// Check if Color is within the Bad Colors Dictionary
//
// @return Nullable<Color>
//
private Color? Bad()
{
if (badColors.ContainsKey(color))
{
try
{
return ColorTranslator.FromHtml(badColors[color]);
}
catch (Exception)
{
return null;
}
}
return null;
}
}
}