色彩插值在.NET 3种颜色之间色彩插值在.NET 3种颜色之间(Color Interpolati

2019-05-12 02:46发布

我想顺利地从A色色彩插值(姑且称之为红)为颜色C(姑且称之为绿色)经过彩色B会(让我们称之为黄色),基于一定的变量的值。

如果变量= 100,我想纯绿色。 如果变量= 50,我想纯黄色。 如果变量= 0,我想纯红。

我明白了,你可以把每个RGB三元在3维空间中的坐标。 我正在寻找的是一个快速和肮脏的线性插值把戏,与.NET颜色类型(ARGB等不同的值)的具体布局干净利落地工作。

Answer 1:

首先,你问的线性插值但你不指定彩色B住在色彩A和C颜色之间的界限; 这是必要的。 其次,你没有指定,但我准备做一个简化的假设彩色B是颜色A和颜色C之间的线的中点; 如果这是不正确下面的代码很容易修改。 最后,我改变了你的假设参数是零和一百之间的整数是零和一之间的两倍。 该代码更容易编写,更容易在后一种情况下明白了,仍然可以与前者(除以你输入一个一百)一起使用。

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 ,乘lambda由两个并返回色彩A和色彩B之间的插值颜色如果参数大于0.5 ,乘lambda由两减一(此地图[0.5, 1][0, 1]并返回彩色B和C.颜色之间内插彩色

如果你不喜欢彩色B住在色彩A和C颜色之间的界限的要求,那么你可以使用正是我刚才所描述做颜色之间的分段线性插值修改。

最后,如果你想插所谓的阿尔法值(“A”在“ARGB”)未指定。 上面的代码很容易修改,以处理这种情况了。 增加一个ComponentSelector定义为color => color.A ,使用InterpolateComponent来内插该值,并使用Color.FromArgb(int, int, int, int)的过载Color.FromArgb



Answer 2:

另一种方法使用高斯分布这样来混合颜色(对于范围为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种颜色的样品:



文章来源: Color Interpolation Between 3 Colors in .NET