簡體   English   中英

在 C# 中將 RGB 顏色轉換為最接近的 ACI 顏色

[英]Converting RGB Colors to closest ACI Color in C#

我目前正在編寫一個與 dxf 文件交互的程序。 因此,我需要一個程序來獲取 RGB 顏色值並返回 AutoCAD 顏色索引 (ACI) 中最接近的顏色

有沒有人有一些代碼或示例如何做到這一點? 如果它是在 C# 中會很好,但它不是必需的。

提前致謝。

從某個來源(例如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 數組中具有最小 dist 的顏色與 r,g,b 最接近。

編輯:正如已經指出的那樣:RGB 距離作為視覺/感知差異並不好。 要匹配視覺差異,請轉換為 HSV/HSL,或者如果您真的雄心勃勃,則可以使用更奇特的色彩空間,例如 CIE XYZ,其中“距離”密切代表相似性。 現在有很好的色彩空間轉換庫,例如五顏六色的https://www.nuget.org/packages/Colourful/

這是將 RGB 轉換為 ACI 的方法

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

我不確定這個線程/問題是否仍然有效,但我也一直在尋找某種方法在互聯網上將顏色轉換為 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。

我不會像安德斯提議的那樣使用硬編碼的 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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM