我想根据某个变量的值,将颜色A(让我们称之为红色)的颜色平滑地插入到颜色C(让我们称之为绿色)通过颜色B(让我们称之为黄色)。 p>
如果变量= 100,我想要纯绿色。 如果变量= 50,我想要纯黄色。 如果变量= 0,我想要纯红色。
据我所知,您可以将每个RGB三元组视为三维空间中的坐标。我正在寻找的是一种快速而肮脏的线性插值技巧,可以与.NET Color类型的特定布局(ARGB的单独值等)一起干净地工作。
答案 0 :(得分:15)
首先,你要求线性插值,但你没有指定颜色B存在于颜色A和颜色C之间的线上;这是必要的。其次,你没有说明,但我将做一个简化的假设,即颜色B是颜色A和颜色C之间的线的中点;如果不是这样,则可以轻松修改以下代码。最后,我改变了你的假设,即参数是0到100之间的整数,是0和1之间的两倍。在后一种情况下,代码更容易编写和更容易理解,并且仍然可以与前者一起使用(将输入除以一百)。
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
乘以2并返回颜色A和颜色B之间的插值颜色。如果参数大于0.5
,将lambda
乘以2并减去一(将[0.5, 1]
映射到[0, 1]
)并返回颜色B和颜色C之间的插值颜色。
如果您不喜欢颜色B位于颜色A和颜色C之间的线上的要求,那么您可以使用我刚才描述的修改来在颜色之间进行分段线性插值。
最后,您没有指定是否要插入所谓的alpha值(“ARGB”中的“A”)。上面的代码很容易修改以处理这种情况。再添加一个ComponentSelector
定义为color => color.A
,使用InterpolateComponent
来插值此值并使用Color.FromArgb(int, int, int, int)
的Color.FromArgb
重载。
答案 1 :(得分:1)
另一种使用高斯分布混合颜色的方法(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种颜色的样本: