Generate Color Gradient in C#

后端 未结 6 841
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-08 19:50

My question here is similar to the question here, except that I am working with C#.

I have two colors, and I have a predefine steps. How to retrieve a list of C

相关标签:
6条回答
  • 2020-12-08 20:22

    Oliver's answer was very close... but in my case some of my stepper numbers needed to be negative. When converting the stepper values into a Color struct my values were going from negative to the higher values e.g. -1 becomes something like 254. I setup my step values individually to fix this.

    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));
        }
    }
    
    0 讨论(0)
  • 2020-12-08 20:22
        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;
        }
    
    0 讨论(0)
  • 2020-12-08 20:27

    Use double instead of 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));
    

    and:

    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));
    
    0 讨论(0)
  • 2020-12-08 20:32

    Maybe this function can help:

    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));
        }
    }
    
    0 讨论(0)
  • 2020-12-08 20:37

    Combining this answer with the idea from several other answers to use floating-point steps, here's a complete method snippet for stepping with floating point. (With integer stepping, I had been getting asymmetrical gradient colors in a 16-color gradient from blue to red.)

    Important difference in this version: you pass the total number of colors you want in the returned gradient sequence, not the number of steps to take within the method implementation.

    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;
    }
    
    0 讨论(0)
  • 2020-12-08 20:39

    You will have to extract the R, G, B components and perform the same linear interpolation on each of them individually, then recombine.

    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));
    }
    
    0 讨论(0)
提交回复
热议问题