我想顺利地从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之间的线的中点; 如果这是不正确下面的代码很容易修改。 最后,我改变了你的假设参数是零和一百之间的整数是零和一之间的两倍。 该代码更容易编写,更容易在后一种情况下明白了,仍然可以与前者(除以你输入一个一百)一起使用。
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
。
另一种方法使用高斯分布这样来混合颜色(对于范围为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种颜色的样品: