7

ある変数の値に基づいて、色A(赤と呼びましょう)から色C(緑と呼びましょう)から色B(黄色と呼びましょう)までスムーズに色を補間したいと思います。

変数=100の場合、純粋な緑が必要です。変数=50の場合、純粋な黄色が必要です。変数=0の場合、純粋な赤が必要です。

各RGBトリプレットを3次元空間の座標として扱うことができると理解しています。私が探しているのは、.NETカラータイプの特定のレイアウト(ARGBなどの個別の値)できれいに機能する、手っ取り早い線形補間のトリックです。

4

2 に答える 2

16

まず、線形補間を要求しますが、色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

于 2009-08-06T03:27:40.287 に答える
4

このようなガウス分布を使用して色をブレンドする別の方法(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色のブレンドのサンプル:

ここに画像の説明を入力してください

于 2014-09-29T15:10:40.567 に答える