Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net NET中3种颜色之间的颜色插值_.net_Colors_Interpolation_System.drawing.color - Fatal编程技术网

.net NET中3种颜色之间的颜色插值

.net NET中3种颜色之间的颜色插值,.net,colors,interpolation,system.drawing.color,.net,Colors,Interpolation,System.drawing.color,我想根据某个变量的值,平滑地插值颜色,从颜色A(我们称之为红色)到颜色C(我们称之为绿色),经过颜色B(我们称之为黄色) 如果变量=100,我想要纯绿色。 如果变量=50,我想要纯黄色。 如果变量=0,我想要纯红色 我知道你可以把每个RGB三元组当作三维空间的坐标。我要寻找的是一个快速而肮脏的线性插值技巧,它可以与.NET颜色类型的特定布局(ARGB等的单独值)完美结合。首先,您要求线性插值,但没有指定颜色B位于颜色a和颜色C之间的线上;这是必要的。第二,您没有指定,但我将做一个简化的假设,即颜

我想根据某个变量的值,平滑地插值颜色,从颜色A(我们称之为红色)到颜色C(我们称之为绿色),经过颜色B(我们称之为黄色)

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


我知道你可以把每个RGB三元组当作三维空间的坐标。我要寻找的是一个快速而肮脏的线性插值技巧,它可以与.NET颜色类型的特定布局(ARGB等的单独值)完美结合。

首先,您要求线性插值,但没有指定颜色B位于颜色a和颜色C之间的线上;这是必要的。第二,您没有指定,但我将做一个简化的假设,即颜色B是颜色a和颜色C之间直线的中点;如果这不是真的,那么下面的代码很容易修改。最后,我改变了你的假设,参数是一个介于0和100之间的整数,变成了介于0和1之间的双精度。在后一种情况下,代码更易于编写和理解,并且仍然可以与前一种情况一起使用(将输入除以100)

类彩色插值器{
委托字节组件选择器(颜色);
静态组件选择器_redSelector=color=>color.R;
静态组件选择器_greenSelector=color=>color.G;
静态组件选择器_blueSelector=color=>color.B;
公共静态颜色插值(
颜色端点1,
颜色端点2,
双λ){
如果(λ<0 | |λ>1){
抛出新ArgumentOutOfRangeException(“lambda”);
}
Color Color=Color.FromRgb(
插值分量(端点1、端点2、λ、_redSelector),
插值分量(端点1,端点2,λ,_greenSelector),
插值分量(端点1、端点2、lambda、_-blueSelector)
);
返回颜色;
}
静态字节内插组件(
颜色端点1,
颜色端点2,
双羔羊,
组件选择器(选择器){
返回(字节)(选择器(端点1)
+(选择器(端点2)-选择器(端点1))*lambda);
}
}
如果颜色B不是颜色A和颜色C之间的中点,如何修改此选项?最简单的方法如下。如果参数(我称之为“
lambda
”)小于
0.5
,将
lambda
乘以2,并返回颜色A和颜色B之间的插值颜色。如果参数大于
0.5
,将
lambda
乘以2,减去1(这将
[0.5,1]
映射到
[0,1]/code>)并返回颜色B和颜色C之间的插值颜色

如果您不喜欢颜色B位于颜色A和颜色C之间的直线上的要求,那么您可以使用我刚才描述的修改,在颜色之间进行分段线性插值


最后,您没有指定是否要插值所谓的alpha值(“ARGB”中的“A”)。上面的代码也很容易修改以处理这种情况。再添加一个定义为
color=>color.A
ComponentSelector
,使用
InterpolateComponent
对该值进行插值,并使用重载。

另一种方法使用高斯分布混合颜色,如下所示(0.0-1.0范围内的任意数量的颜色,以增加混合增加sigma_2值)

更多信息

混合3种颜色的示例:


它不能与三个随机点呈线性关系。请查看详细的响应。正是我要找的!对于一个更通用的解决方案,这可能是值得的。我相信,虽然其他人可能已经回答了最初的问题,但这个回答的效用是无穷的。非常感谢。
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);
    }
}
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);
}