use*_*051 7 .net interpolation colors system.drawing.color
我想根据某个变量的值,将颜色A(让我们称之为红色)的颜色平滑地插入颜色C(让我们称之为绿色)通过颜色B(让我们称之为黄色).
如果变量= 100,我想要纯绿色.如果变量= 50,我想要纯黄色.如果变量= 0,我想要纯红色.
据我所知,您可以将每个RGB三元组视为三维空间中的坐标.我正在寻找的是一种快速而肮脏的线性插值技巧,可以与.NET Color类型的特定布局(ARGB的单独值等)一起干净地工作.
jas*_*son 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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果颜色B不是颜色A和颜色C之间的中点,你如何修改它?最简单的方法如下.如果参数(我称之为" lambda
")小于0.5
,则乘以lambda
2并返回颜色A和颜色B之间的插值颜色.如果参数大于0.5
,则乘以lambda
2并减去1(这映射[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
.
另一种使用高斯分布混合颜色的方法如下(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);
}
Run Code Online (Sandbox Code Playgroud)
更多信息http://en.wikipedia.org/wiki/Normal_distribution
混合 3 种颜色的示例: