2

我让这段代码在 C# 中工作。我想帮助将其翻译成惯用的 PowerShell 脚本,该脚本将 rgb 或 hex 颜色定义作为输入,并将前 3 或 5 个匹配项输出到控制台,包括颜色名称和 rgb 值。我对 PowerShell 很陌生,很抱歉,如果这要求太多。

    private static void FindMyColor()
    {
        System.Drawing.Color targetColor = System.Drawing.Color.FromArgb(red: 0, green: 128, blue: 0);
        var myStuff = EnumerateColors(targetColor: targetColor).OrderBy(tpl => tpl.Item1).ToList();
        int a = 0; // Pause the debugger here.
    }

    private static double GetColorDistance(System.Drawing.Color lhs, System.Drawing.Color rhs)
    {
        double sum = Cube(lhs.R - rhs.R) + Cube(lhs.G - rhs.G) + Cube(lhs.B - rhs.B);
        return Math.Pow(sum, 1.0/3.0);
    }

    private static double Cube(int value)
    {
        return (double) (value * value * value);
    }

    private static System.Collections.Generic.IEnumerable<Tuple<double, string, System.Drawing.Color>> EnumerateColors(System.Drawing.Color targetColor)
    {
        var candidateColors = EnumerateSystemColors();
        foreach (string colorName in candidateColors.Keys)
        {
            var color = candidateColors[key: colorName];
            double colorDistance = GetColorDistance(lhs: color, rhs: targetColor);
            yield return new Tuple<double, string, System.Drawing.Color>(colorDistance, colorName, color);
        }
    }

    private static System.Collections.Generic.Dictionary<string, System.Drawing.Color> EnumerateSystemColors()
    {
        var properties = typeof(System.Drawing.Color)
                .GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy);
        return properties.ToDictionary(p => p.Name, p => (System.Drawing.Color)p.GetValue(null, null));
    }
4

2 回答 2

3

只是为了完整起见,这里有一个 PowerShell 版本,可以找到最接近的颜色。

首先,我们检索Color类型上声明为静态命名属性的所有颜色:

$namedColors = [Drawing.Color] | Get-Member -Static -MemberType Property |
  foreach { [Drawing.Color]::($_.Name) }

为了确定两种颜色之间的距离,我们可以使用笛卡尔距离为三个 RGB 维度定义一个自定义函数:

function Measure-ColorDistance( [Drawing.Color]$a, [Drawing.Color]$b ) {
  $sum = 'R','G','B' | foreach { [Math]::Pow( $a.$_ - $b.$_, 2 ) } | measure -Sum
  [Math]::Round( [Math]::Pow( $sum.Sum, 0.5 ), 2 )
}

为了更容易指定目标颜色,我们可以定义一个辅助函数来创建ARGB颜色值:

function New-Color( [byte]$r = 0, [byte]$g = 0, [byte]$b = 0, [byte]$a = 255 ) {
  [Drawing.Color]::FromArgb( $a, $r, $g, $b )
}

最后,为了找到最接近的颜色,我们可以得到每个命名颜色与目标之间的距离,并返回按该距离排序的顶部颜色:

function MatchColor( [Drawing.Color]$targetColor, [int]$top = 5 ) {
  $distance = @{ n='Distance'; e={ Measure-ColorDistance $targetColor $_ } }
  $distances = $namedColors | Select-Object $distance,Name
  $distances | Sort-Object Distance | Select-Object -First $top
}

调用MatchColor (New-Color -g 128)将显示前五名的结果:

Distance Name
-------- ----
       0 Green
      28 DarkGreen
   49.33 ForestGreen
   99.03 SeaGreen
   99.37 DarkOliveGreen
于 2012-08-05T15:14:17.350 回答
2

为什么不将此代码添加为带有 add-type 的类型?并在 powershell 中使用它[myclass]::GetColorDistance(....)- 有关更多详细信息,请参见此处

添加类型

于 2012-04-19T20:43:10.540 回答