0

I'm trying to create a timer bar for a quiz game which during 10 seconds will shrink in size and fade from green to red.

Here's my existing code:

                double timerWidth = 600;
                double dblRed = 0;
                double dblGreen = 255;
                int intRed = 0;
                int intGreen = 255;

                for (int t = 1000; t != -1; t--) // gives player 10 seconds to select the right answer
                {
                    string strTime = intTime.ToString();
                    lblTime.Text = strTime;
                    intTime--;
                    int intTimerWidth = Convert.ToInt32(timerWidth);
                    imgTimer.Size = new Size(intTimerWidth, 30);
                    dblRed = dblRed + 0.23;
                    dblGreen = dblGreen - 0.23;
                    intRed = Convert.ToInt32(dblRed);
                    intGreen = Convert.ToInt32(dblGreen);
                    imgTimer.BackColor = Color.FromArgb(intRed, intGreen, 0);

                    wait(1); // wait 0.001 seconds
                    timerWidth = timerWidth - 0.6;

                    if (intTime == 0)
                    {
                        checkAnswer(); // when 10 seconds has ellapsed, ellapsed, checks answer

                    }
                }

It functions at current, but using RGB it fades from green to brown to red, which obviously isn't the desired effect. I'm hoping to go from green, to yellow, to orange and then to red which can be achieved through HSL but I can't figure out how to convert to that.

Hope I've asked this okay, I don't frequent these forums.

Thank you!

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
Joshua
  • 41
  • 3
  • Have a look at [this](https://stackoverflow.com/questions/33496284/extract-colour-gradient-pixel-information/33497399#33497399) - Or search for HSL or HSV [conversion](https://stackoverflow.com/questions/1335426/is-there-a-built-in-c-net-system-api-for-hsv-to-rgb) functions. – TaW Nov 14 '20 at 10:20

1 Answers1

1

Here's my library class for converting between RGB and HSL values - I created my own RGB and HSL color classes so that these routines could be used in both Winforms and WPF

public static class perColorConverter
{
    public static perHsla ToHsl(this perRgba rgba)
    {
        return RgbToHsl(rgba.Red, rgba.Green, rgba.Blue, rgba.Alpha);
    }

    public static perHsla RgbToHsl(byte red, byte green, byte blue, byte alpha = 255)
    {
        var min = Math.Min(Math.Min(red, green), blue);
        var max = Math.Max(Math.Max(red, green), blue);
        var delta = Convert.ToSingle(max - min);

        var luminosity = (max + min) / 510f;

        if (Math.Abs(delta) < 0.001f)
        {
            return new perHsla(0f, 0f, luminosity);
        }

        float hue;
        var saturation = luminosity < 0.5
            ? delta / (max + min)
            : delta / (510 - max - min);

        if (red == max)
        {
            hue = (green - blue) / delta;
        }
        else if (green == max)
        {
            hue = 2f + (blue - red) / delta;
        }
        else
        {
            hue = 4f + (red - green) / delta;
        }

        return new perHsla(hue * 60f, saturation, luminosity, alpha);
    }

    public static perRgba ToRgb(this perHsla hsla)
    {
        return HslToRgb(hsla.Hue, hsla.Saturation, hsla.Luminosity, hsla.Alpha);
    }

    public static perRgba HslToRgb(float hue, float saturation, float luminosity)
    {
        return HslToRgb(hue, saturation, luminosity, 255);
    }

    public static perRgba HslToRgb(float hue, float saturation, float luminosity, byte alpha)
    {
        byte red, green, blue;

        // zero saturation => some shade of grey
        if (Math.Abs(saturation) < 0.001f)
        {
            red = Convert.ToByte(luminosity * 255);
            green = red;
            blue = red;
        }
        else
        {
            var t2 = luminosity < 0.5f
                ? luminosity * (1.0f + saturation)
                : luminosity + saturation - (luminosity * saturation);
            var t1 = (2 * luminosity) - t2;

            red = HueToRgb(t1, t2, hue + 120);
            green = HueToRgb(t1, t2, hue);
            blue = HueToRgb(t1, t2, hue - 120);
        }

        return new perRgba(red, green, blue, alpha);
    }

    private static byte HueToRgb(float t1, float t2, float hue)
    {
        while (hue >= 360)
        {
            hue -= 360;
        }

        while (hue < 0)
        {
            hue += 360;
        }

        float x;
        if (hue < 60)
        {
            x = t1 + (t2 - t1) * hue / 60;
        }
        else if (hue < 180)
        {
            x = t2;
        }
        else if (hue < 240)
        {
            x = t1 + (t2 - t1) * (240 - hue) / 60;
        }
        else
        {
            x = t1;
        }

        return Convert.ToByte(x * 255);
    }
}

For your requirment, generate the appropriate start and end HSL values, and using a linear interpolation calculate Hue, Saturation & Luminosity values for each step of the transition, which you can convert into the equivalent RGB value.

More details on HSL usage on my blog post.

Peregrine
  • 4,287
  • 3
  • 17
  • 34