如何根据C#中的一系列值计算颜色?

时间:2010-02-21 22:34:08

标签: c# colors system.drawing.color

var colors = new Color[] { 
    Color.Blue, 
    Color.Green, 
    Color.Yellow, 
    Color.Orange, 
    Color.Red 
};

var min = 0;
var max = 400;

我正在尝试根据另一个数字获取这些值之间的颜色。因此,例如,如果我想要值350的颜色,它将是50%橙色和50%红色。

编辑 - 为了清晰而重新编辑

我能想到的唯一方法是在photoshop中创建渐变图像,然后计算偏移并抓取像素RGB值。然而,这似乎非常hacky,我想通过某种计算来做到这一点。

有什么想法吗?

5 个答案:

答案 0 :(得分:11)

您可以使用线性插值来混合R,G和B值(如果需要,可以使用A)。这是Windows窗体项目的一些示例代码。只需添加范围为0到400的轨道栏,并将轨迹栏的滚动事件连接到下面的处理程序:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    byte interpolate(byte a, byte b, double p)
    {
        return (byte)(a * (1 - p) + b * p);
    }

    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        int v = trackBar1.Value;
        BackColor = getColor(v);
    }

    private Color getColor(int v)
    {
        SortedDictionary<int, Color> d = new SortedDictionary<int, Color>();
        d.Add(0, Color.Blue);
        d.Add(100, Color.Green);
        d.Add(200, Color.Yellow);
        d.Add(300, Color.Orange);
        d.Add(400, Color.Red);

        KeyValuePair<int, Color> kvp_previous = new KeyValuePair<int,Color>(-1, Color.Black);
        foreach (KeyValuePair<int, Color> kvp in d)
        {
            if (kvp.Key > v)
            {
                double p = (v - kvp_previous.Key) / (double)(kvp.Key - kvp_previous.Key);
                Color a = kvp_previous.Value;
                Color b = kvp.Value;
                Color c = Color.FromArgb(
                    interpolate(a.R, b.R, p),
                    interpolate(a.G, b.G, p),
                    interpolate(a.B, b.B, p));
                return c;
            }
            kvp_previous = kvp;
        }

        return Color.Black;
    }
}

你也可以按照nobugz的建议使用HSL颜色。

注意:此代码只是概念验证。在实际应用程序中,您需要创建一个类来封装颜色选择逻辑,使其更具可定制性,以及错误处理等。它还没有针对速度进行优化。如果速度是一个重要的考虑因素,那么你应该使用查找表。

答案 1 :(得分:4)

Mark Byers答案中有一个小错误,需要将其修改为:

if (kvp.Key > v)
{
    double p = (v - kvp_previous.Key) / (double)(kvp.Key - kvp_previous.Key);
    Color a = kvp_previous.Value;
    Color b = kvp.Value;
    Color c = Color.FromArgb(
        interpolate(a.R, b.R, p),
        interpolate(a.G, b.G, p),
        interpolate(a.B, b.B, p));
    return c;
}
else if (kvp.Key == v)
{
    return kvp.Value;
}

否则任何等于其中一个输入点的内容将返回为黑色。 (我没有足够的声誉评论他的答案,所以据我所知这是我唯一的办法)

答案 2 :(得分:2)

概括解决方案的另一种方法

/// <summary>
/// Interpolate colors 0.0 - 1.0        
/// </summary>        
public static Color Interpolate(double percent, params Color[] colors)
{
    int left = (int)Math.Floor(percent * (colors.Length - 1));
    int right = (int)Math.Ceiling(percent * (colors.Length - 1));
    Color colorLeft = colors[left];
    Color colorRight = colors[right];

    double step = 1.0 / (colors.Length - 1);
    double percentRight = (percent - (left * step)) / step;
    double percentLeft = 1.0 - percentRight;

    Color outputColor = new Color();

    outputColor.R = (byte)(colorLeft.R * percentLeft + colorRight.R * percentRight);
    outputColor.G = (byte)(colorLeft.G * percentLeft + colorRight.G * percentRight);
    outputColor.B = (byte)(colorLeft.B * percentLeft + colorRight.B * percentRight);
    outputColor.A = (byte)(colorLeft.A * percentLeft + colorRight.A * percentRight);

    return outputColor;
}

答案 3 :(得分:1)

这样的东西可能对你有用......但是,这完全没有经过考验。这个想法是你计算你需要的两种颜色,然后根据你可以计算的百分比值混合这两种颜色。如上所述,完全未经测试。

using System.Convert;

public static Color oddColorFunction(int value)
{
    Color colors = new Color[] { Color.Blue, Color.Green, Color.Yellow, Color.Orange, Color.Red };
    int min = 0;
    int max = 400;

    decimal range = max / colors.Length;

    Color leftColor = ToInt32(Decimal.Floor(value / range));
    Color rightColor = ToInt32(Decimal.Ceiling(value / range));

    return mixColors(colors[leftColor], colors[rightColor], ToInt32(Decimal.Round(value % range * 100)));
}

public static mixColors(Color colorA, Color colorB, int percentage)
{
    //combine colors here based on percentage
    //I'm to lazy to code this :P
}

答案 4 :(得分:0)

Color has the properties R, G, and B。您可以获取输入值,将其除以100以获得底部颜色(将其剪切为3)。添加一个以获得顶部颜色。然后从底部和顶部颜色中抓取R,G和B,根据值%100创建每个颜色的加权平均值,并使用这些值创建一个新颜色。