使用PowerShell查找最近的System.Color实例

时间:2012-04-19 18:02:43

标签: c# powershell

我在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));
    }

2 个答案:

答案 0 :(得分:2)

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

Add-Type

答案 1 :(得分:2)

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

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

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

要确定两种颜色之间的距离,我们可以使用Cartesian distance为三个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
相关问题