Dot-Net

.NET 中 3 種顏色之間的顏色插值

  • August 14, 2017

我想根據某個變數的值將顏色 A(我們稱之為紅色)通過顏色 B(我們稱之為黃色)平滑地插入顏色 C(我們稱之為綠色)。

如果變數 = 100,我想要純綠色。如果變數 = 50,我想要純黃色。如果變數 = 0,我想要純紅色。

我知道您可以將每個 RGB 三元組視為 3 維空間中的座標。我正在尋找的是一種快速而簡單的線性插值技巧,它可以與 .NET Color 類型的特定佈局(ARGB 等的單獨值)完美配合。

首先,您要求進行線性插值,但沒有指定顏色 B 位於顏色 A 和顏色 C 之間的線上;這是必要的。其次,您沒有指定,但我將做一個簡化的假設,即顏色 B 是顏色 A 和顏色 C 之間的線的中點;如果不是這樣,以下程式碼很容易修改。最後,我改變了你的假設,即參數是介於零和一百之間的整數,是介於零和一之間的雙精度數。在後一種情況下,程式碼更容易編寫和理解,並且仍然可以與前者一起使用(將您的輸入除以 100)。

class ColorInterpolator {
   delegate byte ComponentSelector(Color color);
   static ComponentSelector _redSelector = color => color.R;
   static ComponentSelector _greenSelector = color => color.G;
   static ComponentSelector _blueSelector = color => color.B;

   public static Color InterpolateBetween(
       Color endPoint1,
       Color endPoint2,
       double lambda) {
       if (lambda < 0 || lambda > 1) {
           throw new ArgumentOutOfRangeException("lambda");
       }
       Color color = Color.FromRgb(
           InterpolateComponent(endPoint1, endPoint2, lambda, _redSelector),
           InterpolateComponent(endPoint1, endPoint2, lambda, _greenSelector),
           InterpolateComponent(endPoint1, endPoint2, lambda, _blueSelector)
       );

       return color;
   }

   static byte InterpolateComponent(
       Color endPoint1,
       Color endPoint2,
       double lambda,
       ComponentSelector selector) {
       return (byte)(selector(endPoint1)
           + (selector(endPoint2) - selector(endPoint1)) * lambda);
   }
}

如果顏色 B 不是顏色 A 和顏色 C 之間的中點,你如何修改它?最簡單的方法如下。如果參數(我稱之為“ lambda”)小於0.5,乘以lambda2 並返回顏色 A 和顏色 B 之間的插值顏色。如果參數大於0.5,乘以lambda2 並減去 1(這映射[0.5, 1][0, 1])並返回顏色 B 和顏色 C 之間的插值顏色。

如果您不喜歡顏色 B 位於顏色 A 和顏色 C 之間的線上的要求,那麼您可以完全使用我剛剛描述的修改在顏色之間進行分段線性插值。

最後,您沒有指定是否要插入所謂的 alpha 值(“ARGB”中的“A”)。上面的程式碼也很容易修改以處理這種情況。再添加一個ComponentSelector定義為color => color.A,用於InterpolateComponent插入該值並使用 的Color.FromArgb(int, int, int, int)重載Color.FromArgb

引用自:https://stackoverflow.com/questions/1236683