【问题标题】:C# Round Color to Colors in a listC#圆形颜色到列表中的颜色
【发布时间】:2011-07-28 14:57:37
【问题描述】:

我有一个 HEX 格式的颜色列表:

String[] validcolors = new String[]
{
    "0055A5",
    "101010",
    "E4D200",
    "FFFFFF",
    "006563",
    "A97B3E",
    "B80000",
    "6E3391",
    "D191C3",
    "D68200",
    "60823C",
    "AA8D73",
    "73A1B8",
    "6E6D6E",
    "00582C",
    "604421"
};    

还有一个颜色对象:

Color c = ...

我想在validcolors 中找到最接近c 的颜色。有人可以帮帮我吗?我最初的想法是“最接近 RGB 值”,但不管怎样都行。

【问题讨论】:

  • 最接近 RGB 值是我试图实现的。
  • 我误解了这个问题。我将删除我的答案,但将此字符串保留为颜色转换:Color.FromArgb(int.Parse(s.Substring(0, 2), NumberStyles.HexNumber), int.Parse(...
  • 在 RGB 颜色模型中执行此操作可能会产生一些非常奇怪的结果。至少它们看起来根本不像匹配项不是人眼。如果您想以正确的方式执行此操作,则应将颜色转换为 HSV/HSB 或 HSL 颜色空间。是的,它们是不同的,但在这种情况下,哪个并不重要。它们更好地模拟了人类对颜色的感知。获得匹配后,您可以转换回 RGB。
  • 哈哈,是的,我从实现 manji 的答案中注意到...我将对其进行修改以使用 HSV,并发布结果

标签: c# colors rounding


【解决方案1】:

我会考虑将十六进制转换为 .NET 颜色,然后计算某种距离 ((x2-x1)²+(y2-y1)²) 并使用此距离取最近的:

string closestColor = "";
double diff = 200000; // > 255²x3

foreach(string colorHex in validColors)
{
    Color color = System.Drawing.ColorTranslator.FromHtml("#"+colorHex);
    if(diff > (diff = (c.R - color.R)²+(c.G - color.G)²+(c.B - color.B)²))
        closestColor = colorHex;
}

return closestColor;

【讨论】:

  • 谢谢!如果我使用这种方法(效果很好),它会产生奇怪的结果,就像 Cody 说的那样。就像他建议的那样,修改方法以使用 HSV 解决了问题。
  • 你是如何修改它以使用 HSV 的?
【解决方案2】:

两种颜色之间的距离取决于您使用的颜色模型。 See this article in the Wikipedia 因此,在我们知道您喜欢哪种型号之前,我们无能为力。

【讨论】:

    【解决方案3】:

    这是一种使用 HSB 的(详细)方法。

    float targetHue = c.GetHue();
    float targetSat = c.GetSaturation();
    float targetBri = c.GetBrightness();
    
    string closestColor = "";
    double smallestDiff = double.MaxValue;
    
    foreach (string colorHex in validcolors)
    {
        Color currentColor = ColorTranslator.FromHtml("#" + colorHex);
        float currentHue = currentColor.GetHue();
        float currentSat = currentColor.GetSaturation();
        float currentBri = currentColor.GetBrightness();
    
        double currentDiff = Math.Pow(targetHue - currentHue, 2) + Math.Pow(targetSat - currentSat, 2) + Math.Pow(targetBri - currentBri, 2);
    
        if (currentDiff < smallestDiff)
        {
            smallestDiff = currentDiff;
            closestColor = colorHex;
        }
    }
    
    return closestColor;
    

    【讨论】:

      猜你喜欢
      • 2010-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 2019-06-12
      • 2018-05-27
      • 2021-02-02
      • 2018-09-05
      相关资源
      最近更新 更多