ある変数の値に基づいて、色A(赤と呼びましょう)から色C(緑と呼びましょう)から色B(黄色と呼びましょう)までスムーズに色を補間したいと思います。
変数=100の場合、純粋な緑が必要です。変数=50の場合、純粋な黄色が必要です。変数=0の場合、純粋な赤が必要です。
各RGBトリプレットを3次元空間の座標として扱うことができると理解しています。私が探しているのは、.NETカラータイプの特定のレイアウト(ARGBなどの個別の値)できれいに機能する、手っ取り早い線形補間のトリックです。
ある変数の値に基づいて、色A(赤と呼びましょう)から色C(緑と呼びましょう)から色B(黄色と呼びましょう)までスムーズに色を補間したいと思います。
変数=100の場合、純粋な緑が必要です。変数=50の場合、純粋な黄色が必要です。変数=0の場合、純粋な赤が必要です。
各RGBトリプレットを3次元空間の座標として扱うことができると理解しています。私が探しているのは、.NETカラータイプの特定のレイアウト(ARGBなどの個別の値)できれいに機能する、手っ取り早い線形補間のトリックです。
まず、線形補間を要求しますが、色Bが色Aと色Cの間の線上にあることを指定しません。これは必要です。次に、指定しませんでしたが、色Bが色Aと色Cの間の線の中間点であるという単純化した仮定を立てます。これが当てはまらない場合、次のコードは簡単に変更できます。最後に、パラメータが0から100の間の整数であるという仮定を、0から1の間のdoubleになるように変更しました。後者の場合、コードは記述しやすく、理解しやすく、前者でも使用できます(入力を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」と呼んでいるもの)が。未満の場合は、2を0.5掛けlambdaて、色Aと色Bの間の補間色を返します。パラメータがより大きい場合は、2を0.5掛けlambdaて1を引いて(これはにマッピング[0.5, 1]されます[0, 1])、色Bと色Cの間の補間色。
色Bが色Aと色Cの間の線上にあるという要件が気に入らない場合は、先ほど説明した変更を使用して、色間で区分的線形補間を行うことができます。
最後に、いわゆるアルファ値(「ARGB」の「A」)を補間するかどうかを指定しませんでした。上記のコードは、この状況にも対応できるように簡単に変更できます。ComponentSelectorとして定義されたものをもう1つ追加し、この値を補間するために使用し、のcolor => color.Aオーバーロードを使用します。InterpolateComponentColor.FromArgb(int, int, int, int)Color.FromArgb
このようなガウス分布を使用して色をブレンドする別の方法(0.0〜1.0の範囲の任意の数の色、ブレンドを増やすにはsigma_2値を増やす)
public static Color InterpolateColor(Color[] colors, double x)
{
double r = 0.0, g = 0.0, b = 0.0;
double total = 0.0;
double step = 1.0 / (double)(colors.Length - 1);
double mu = 0.0;
double sigma_2 = 0.035;
foreach (Color color in colors)
{
total += Math.Exp(-(x - mu) * (x - mu) / (2.0 * sigma_2)) / Math.Sqrt(2.0 * Math.PI * sigma_2);
mu += step;
}
mu = 0.0;
foreach(Color color in colors)
{
double percent = Math.Exp(-(x - mu) * (x - mu) / (2.0 * sigma_2)) / Math.Sqrt(2.0 * Math.PI * sigma_2);
mu += step;
r += color.R * percent / total;
g += color.G * percent / total;
b += color.B * percent / total;
}
return Color.FromArgb(255, (int)r, (int)g, (int)b);
}
詳細情報http://en.wikipedia.org/wiki/Normal_distribution
3色のブレンドのサンプル:
