【问题标题】:Converting RGB Colors to closest ACI Color in C#在 C# 中将 RGB 颜色转换为最接近的 ACI 颜色
【发布时间】:2011-09-05 14:33:41
【问题描述】:

我目前正在编写一个与 dxf 文件交互的程序。因此,我需要一个接受 RGB 颜色值并返回 AutoCAD 颜色索引 (ACI) 中最接近的颜色的例程

有人有一些代码或示例如何做到这一点吗?如果是 C# 就好了,但没必要。

提前致谢。

【问题讨论】:

    标签: c# colors rgb autocad dxf


    【解决方案1】:

    从某个来源(例如http://www.jtbworld.com/lisp/DisplayColorProperties.htm)获取所有 ACI 颜色的 RGB 值并创建 ACI 颜色数组。要按索引获取 ACI 颜色,只需从该列表中选择颜色即可。

    要从 RGB 进行“最接近”匹配向后查找,只需通过该数组并返回具有最小距离的颜色(例如通过检查 3 个颜色通道的平方距离:如果您的颜色是 r,g ,b 且 aci 颜色为 R,G,B 则距离为

    dist = (r-R)*(r-R) + (g-G)*(g-G) + (b-B)*(b-B);
    

    ACI 数组中具有最小距离的颜色与 r,g,b 最接近。

    编辑:正如已经指出的那样:RGB 距离作为视觉/感知差异不好。要匹配视觉差异,请转换为 HSV/HSL,或者如果您真的有野心,可以使用更具异国情调的色彩空间,例如 CIE XYZ,其中“距离”密切代表相似性。这些天有很好的颜色空间转换库,例如Colorful https://www.nuget.org/packages/Colourful/

    【讨论】:

    • 在 RGB 空间中查找最接近的匹配对 RGB 不起作用(例如 rgb(200,230,255) 将匹配到 aci="254")。使用 HSV 模型获得更好的结果。
    • 好点。添加了关于色彩空间转换的说明。
    【解决方案2】:

    我不会像 Anders 建议的那样为 ACI 颜色的硬编码数组而烦恼。您可以从每个合法索引中获取 AutoCAD Color 对象,并从中提取 RGB 值作为具有 ColorValue 属性的 System.Drawing.Color

    这是基于 Anders 其余回复的完整解决方案,将 Math.Pow(r - R, 2) 替换为 (r - R)*(r - R),因为在我看来更清楚地表达了“距离”计算的毕达哥拉斯意图。

    byte r = 1, g = 203, b = 103; // input color
    double minDist = double.MaxValue;
    short match = 0; // this will end up with our answer
    for (short i = 1; i <= 255; ++i)
    {
        var color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, i);
        System.Drawing.Color rgb = color.ColorValue;
        double dist =
            Math.Pow(r - rgb.R, 2) +
            Math.Pow(g - rgb.G, 2) +
            Math.Pow(b - rgb.B, 2);
        if (dist < minDist)
        {
            minDist = dist;
            match = i;
        }
    }
    

    【讨论】:

      【解决方案3】:

      这是将 RGB 转换为 ACI 的方法

      var color = Autodesk.AutoCAD.Colors.Color(r, g, b);
      

      【讨论】:

        【解决方案4】:

        我不确定这个线程/问题是否仍然有效,但我也一直在寻找某种方法将颜色转换为 Internet 上的 ACI,但失败了。就我而言,我需要一种最好避免使用外部库和 CAD 函数的方法。

        我对 C# 无能为力。我通常与 Lazarus/Free Pascal 一起工作,经过大量试验后,我得出了一个似乎对我来说效果很好的功能。所以我在这里发布我的代码,以防它们对你或其他人有帮助。

        我的代码如下:

        Function RGB2ACIDXFColor(MyColor : TColor) : Integer ;
        Var
           OldCol, LowR, MidR, HiR : String ;
           RCol, GCol, BCol, LowCol, MidCol, HiCol : Integer ;
           StPt, HRatio, VRatio, Hemis : Integer ;
        Begin
        Result := 10 ;
        {Break Color Component (BGR Color)}
        {IntToHex & Hex2Dec are functions from Lazarus Libraries}
        OldCol := IntToHex(MyColor,6) ;    
        BCol := Hex2Dec(Copy(OldCol,1,2)) ;
        GCol := Hex2Dec(Copy(OldCol,3,2)) ;
        RCol := Hex2Dec(Copy(OldCol,5,2)) ;
        
        {Find Color Component Priorities}
        LowCol := RCol ;
        LowR := 'R' ;
        If (GCol < LowCol) Then
        Begin
             LowCol := GCol ;
             LowR := 'G' ;
        End; //If
        If (BCol < LowCol) Then
        Begin
             LowCol := BCol ;
             LowR := 'B' ;
        End; //If
        
        HiCol := RCol ;
        HiR := 'R' ;
        If (GCol > HiCol) Then
        Begin
             HiCol := GCol ;
             HiR := 'G' ;
        End; //If
        If (BCol > HiCol) Then
        Begin
             HiCol := BCol ;
             HiR := 'B' ;
        End; //If
        
        MidCol := GCol ;
        MidR := 'G' ;
        If ((HiR = 'G') AND (LowR = 'R')) OR
           ((HiR = 'R') AND (LowR = 'G')) Then
        Begin
             MidCol := BCol ;
             MidR := 'B' ;
        End; //If
        If ((HiR = 'G') AND (LowR = 'B')) OR
           ((HiR = 'B') AND (LowR = 'G')) Then
        Begin
             MidCol := RCol ;
             MidR := 'R' ;
        End; //If
        
        {Refer to CAD color table}
        {Find Color Row}
        VRatio := Round((5 * (255 - HiCol)) / 255) ;
        VRatio *= 2 ;
        {Find Color Hemisphere}
        If (LowCol = 0) Then Hemis := 0 Else Hemis := 1 ;
        
        {Find Color Start Column And Incrementation}
        If (LowR = 'B') Then
        Begin
             HRatio := Round((8 * GCol) / (GCol + RCol)) ;
             Result := 10 ;
        End; //If
        If (LowR = 'G') Then
        Begin
             HRatio := Round((8 * RCol) / (RCol + BCol)) ;
             Result := 170 ;
        End; //If
        If (LowR = 'R') Then
        Begin
             HRatio := Round((8 * BCol) / (BCol + GCol)) ;
             Result := 90 ;
        End; //If
        
        HRatio *= 10 ;
        Result += HRatio + VRatio + Hemis ;
        If (Result > 249) Then Result -= 240 ;
        End; //Sub
        

        我相信您能够将其翻译成 C#,并希望这对某人有用。

        干杯,

        J-埃里克·J。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-10-28
          • 2019-07-02
          • 2019-02-08
          • 2019-08-17
          • 2018-06-16
          • 2013-04-12
          • 2013-12-05
          • 2012-07-27
          相关资源
          最近更新 更多