現在、dxf ファイルと対話するプログラムを作成しています。したがって、RGB カラー値を取得し、AutoCAD カラー インデックス (ACI) で最も近い色を返すルーチンが必要です。
誰かがコードやその方法の例を持っていますか? C# であればいいのですが、必須ではありません。
前もって感謝します。
いくつかのソース(たとえばhttp://www.jtbworld.com/lisp/DisplayColorProperties.htm)からすべてのACIカラーのRGB値を取得し、ACIカラーの配列を作成します。インデックスでACIの色を取得するには、そのリストから色を選択するだけです。
RGBから「最も近い」一致の後方ルックアップを実行するには、その配列をパスして、最小距離で色を返します(たとえば、3つのカラーチャネルの距離の2乗を確認します。色が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に変換するか、本当に野心的な場合は、「距離」が類似性を厳密に表すCIEXYZのようなよりエキゾチックな色空間に変換します。最近では、Colorfulhttps ://www.nuget.org/packages/Colourful/などの色空間変換に適したライブラリがあります。
Andersが提案しているように、ハードコードされたACIカラーの配列を気にする必要はありません。各リーガルインデックスからAutoCADColor
オブジェクトを取得System.Drawing.Color
し、ColorValue
プロパティを使用してそこからRGB値を抽出できます。
これは、アンダースの残りの応答に基づく完全な解決策です。これは、「距離」計算のピタゴラスの意図をより明確に表現しているように思われる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;
}
}
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.