【问题标题】:Generate Color Gradient in C#在 C# 中生成颜色渐变
【发布时间】:2011-01-01 23:32:31
【问题描述】:

我的问题与the question here 类似,只是我使用的是 C#。

我有两种颜色,并且我有预定义的步骤。如何检索Colors 的列表,它们是两者之间的梯度?

这是我尝试过的一种方法,但没有奏效:

int argbMax = Color.Chocolate.ToArgb();
int argbMin = Color.Blue.ToArgb();
var colorList = new List<Color>();

for(int i=0; i<size; i++)
{
    var colorAverage= argbMin + (int)((argbMax - argbMin) *i/size);
    colorList.Add(Color.FromArgb(colorAverage));
}

如果你尝试上面的代码,你会发现argb的渐变与颜色的视觉渐变并不对应。

对此有什么想法吗?

【问题讨论】:

    标签: c# .net colors system.drawing.color


    【解决方案1】:

    您必须提取 R、G、B 分量并分别对它们中的每一个执行相同的线性插值,然后重新组合。

    int rMax = Color.Chocolate.R;
    int rMin = Color.Blue.R;
    // ... and for B, G
    var colorList = new List<Color>();
    for(int i=0; i<size; i++)
    {
        var rAverage = rMin + (int)((rMax - rMin) * i / size);
        var gAverage = gMin + (int)((gMax - gMin) * i / size);
        var bAverage = bMin + (int)((bMax - bMin) * i / size);
        colorList.Add(Color.FromArgb(rAverage, gAverage, bAverage));
    }
    

    【讨论】:

    • 我知道这是旧的,但它被标记为答案。事实上,如果“大小”导致某个颜色的 R、G 或 B 值的范围在 0 到 255 之间,这将引发异常。
    • 我认为不会。它在两个起始颜色之间线性插值每个组件。只有无效的输入颜色会导致您注意到的效果。除法 (i / size)(如果被视为非整数)不能产生小于 0 或大于 1 的值。即使除以零的可能性也受到 for 循环条件的保护。所以我认为任何大小的值都不会导致问题,可能只是输入的 RGB 值。
    【解决方案2】:

    Oliver 的答案非常接近……但在我的情况下,我的一些步进数字需要为负数。将步进值转换为 Color 结构时,我的值从负值变为更高的值,例如-1 变成 254 之类的东西。我单独设置我的步长值来解决这个问题。

    public static IEnumerable<Color> GetGradients(Color start, Color end, int steps)
    {
        int stepA = ((end.A - start.A) / (steps - 1));
        int stepR = ((end.R - start.R) / (steps - 1));
        int stepG = ((end.G - start.G) / (steps - 1));
        int stepB = ((end.B - start.B) / (steps - 1));
    
        for (int i = 0; i < steps; i++)
        {
            yield return Color.FromArgb(start.A + (stepA * i),
                                        start.R + (stepR * i),
                                        start.G + (stepG * i),
                                        start.B + (stepB * i));
        }
    }
    

    【讨论】:

    • 这非常简单,看起来很棒并且有效。谢谢:-)
    【解决方案3】:

    也许这个功能可以帮助:

    public IEnumerable<Color> GetGradients(Color start, Color end, int steps)
    {
        Color stepper = Color.FromArgb((byte)((end.A - start.A) / (steps - 1)),
                                       (byte)((end.R - start.R) / (steps - 1)),
                                       (byte)((end.G - start.G) / (steps - 1)),
                                       (byte)((end.B - start.B) / (steps - 1)));
    
        for (int i = 0; i < steps; i++)
        {
            yield return Color.FromArgb(start.A + (stepper.A * i),
                                        start.R + (stepper.R * i),
                                        start.G + (stepper.G * i),
                                        start.B + (stepper.B * i));
        }
    }
    

    【讨论】:

    • 这非常接近,但我有一些负步长值破坏了它。我也发布了我修改后的解决方案。
    【解决方案4】:
        public static List<Color> GetGradientColors(Color start, Color end, int steps)
        {
            return GetGradientColors(start, end, steps, 0, steps - 1);
        }
    
        public static List<Color> GetGradientColors(Color start, Color end, int steps, int firstStep, int lastStep)
        {
            var colorList = new List<Color>();
            if (steps <= 0 || firstStep < 0 || lastStep > steps - 1)
                return colorList;
    
            double aStep = (end.A - start.A) / steps;
            double rStep = (end.R - start.R) / steps;
            double gStep = (end.G - start.G) / steps;
            double bStep = (end.B - start.B) / steps;
    
            for (int i = firstStep; i < lastStep; i++)
            {
                var a = start.A + (int)(aStep * i);
                var r = start.R + (int)(rStep * i);
                var g = start.G + (int)(gStep * i);
                var b = start.B + (int)(bStep * i);
                colorList.Add(Color.FromArgb(a, r, g, b));
            }
    
            return colorList;
        }
    

    【讨论】:

      【解决方案5】:

      使用 double 代替 int:

      double stepA = ((end.A - start.A) / (double)(steps - 1));
      double stepR = ((end.R - start.R) / (double)(steps - 1));
      double stepG = ((end.G - start.G) / (double)(steps - 1));
      double stepB = ((end.B - start.B) / (double)(steps - 1));
      

      和:

      yield return Color.FromArgb((int)start.A + (int)(stepA * step),
                                                  (int)start.R + (int)(stepR * step),
                                                  (int)start.G + (int)(stepG * step),
                                                  (int)start.B + (int)(stepB * step));
      

      【讨论】:

        【解决方案6】:

        结合this answer 与其他几个答案的想法来使用浮点步骤,这里有一个完整的方法 sn-p 用于浮点步进。 (通过整数步进,我得到了从蓝色到红色的 16 色渐变中的不对称渐变颜色。)

        此版本的重要区别:您在返回的渐变序列中传递所需的颜色总数,而不是方法实现中要采取的步骤数。

        public static IEnumerable<Color> GetColorGradient(Color from, Color to, int totalNumberOfColors)
        {
            if (totalNumberOfColors < 2)
            {
                throw new ArgumentException("Gradient cannot have less than two colors.", nameof(totalNumberOfColors));
            }
        
            double diffA = to.A - from.A;
            double diffR = to.R - from.R;
            double diffG = to.G - from.G;
            double diffB = to.B - from.B;
        
            var steps = totalNumberOfColors - 1;
        
            var stepA = diffA / steps;
            var stepR = diffR / steps;
            var stepG = diffG / steps;
            var stepB = diffB / steps;
        
            yield return from;
        
            for (var i = 1; i < steps; ++i)
            {
                yield return Color.FromArgb(
                    c(from.A, stepA),
                    c(from.R, stepR),
                    c(from.G, stepG),
                    c(from.B, stepB));
        
                int c(int fromC, double stepC)
                {
                    return (int)Math.Round(fromC + stepC * i);
                }
            }
        
            yield return to;
        }
        

        【讨论】:

          猜你喜欢
          • 2010-11-19
          • 1970-01-01
          • 2011-03-31
          • 1970-01-01
          • 2012-01-03
          • 1970-01-01
          • 2012-11-28
          • 1970-01-01
          相关资源
          最近更新 更多