5

I'm trying to use the answer of the question found here I have a problem with using the color class. For example,Color.Red.Range(Color.Green, numberOfIntermediateColors); an error appears saying" 'System.Windows.Media.Color' does not contain a definition for 'Red' " Same withGetBrightness,GetSaturation and GetHue there is an error saying "'System.Windows.Media.Color' does not contain a definition for 'GetSaturation' and no extension method 'GetSaturation' accepting a first argument of type 'System.Windows.Media.Color' could be found (are you missing a using directive or an assembly reference?) "

So could anyone could please advise how to use the proposed answer in Wpf?

Community
  • 1
  • 1
Tak
  • 3,536
  • 11
  • 51
  • 93
  • 1
    Sounds like you're missing a reference. Right-click on References under your project and select `Add Reference...` – M.Babcock Sep 17 '13 at 01:59
  • Thanks for your comment! As stated in my question, I've already added the `System.Drawing` reference, but still when in my code I type `System.` the reference `Drawing` don't appear – Tak Sep 17 '13 at 02:04
  • 1
    What `Range` function? `System.Drawing.Color` does not define that method. And you'd need to convert back to a WPF color too. – Kent Boogaart Sep 17 '13 at 02:11
  • 1
    There is no Range in `System.Drawing.Color` http://msdn.microsoft.com/en-us/library/system.drawing.color.aspx or `System.Windos.Media.Color` http://msdn.microsoft.com/en-us/library/system.windows.media.color.aspx – sa_ddam213 Sep 17 '13 at 02:16
  • @KentBoogaart sorry I I've done a mistake! I'll update my question – Tak Sep 17 '13 at 02:25
  • @sa_ddam213 sorry I I've done a mistake! I'll update my question – Tak Sep 17 '13 at 02:25
  • What I'm trying to do is to apply the answer found here in WPF http://stackoverflow.com/questions/18821696/use-hsv-instead-of-rgb-in-wpf – Tak Sep 17 '13 at 02:26
  • @KentBoogaart I've updated my question, so if you could please have a look. Many Thanks – Tak Sep 17 '13 at 02:54
  • @sa_ddam213 I've updated my question, so if you could please have a look. Many Thanks – Tak Sep 17 '13 at 02:55

3 Answers3

11

Use the following extension methods:

public static float GetHue(this System.Windows.Media.Color c) =>
  System.Drawing.Color.FromArgb(c.A, c.R, c.G, c.B).GetHue();

public static float GetBrightness(this System.Windows.Media.Color c) =>
  System.Drawing.Color.FromArgb(c.A, c.R, c.G, c.B).GetBrightness();

public static float GetSaturation(this System.Windows.Media.Color c) =>
  System.Drawing.Color.FromArgb(c.A, c.R, c.G, c.B).GetSaturation();
Gábor
  • 9,466
  • 3
  • 65
  • 79
1

Not sure what the problem is but I copied the code from the other 2 answers and it seems to work fine if you add the System.Drawing namespace and fix up the ambiguities

int numberOfIntermediateColors = 8;
IEnumerable<System.Drawing.Color> colorPalette = System.Drawing.Color.Red.Range(System.Drawing.Color.Green, numberOfIntermediateColors);
// returns 8 colors in that range.

Range Extension method

public static class ColorExtensions
{
    public static IEnumerable<System.Drawing.Color> Range(this System.Drawing.Color firstColor, System.Drawing.Color lastColor, int count)
    {
        float stepHueClockwise = GetStepping(firstColor.GetHue(), lastColor.GetHue(), count, Direction.Clockwise);
        float stepHueCounterClockwise = GetStepping(firstColor.GetHue(), lastColor.GetHue(), count, Direction.CounterClockwise);

        if (Math.Abs(stepHueClockwise) >= Math.Abs(stepHueCounterClockwise))
            return Range(firstColor, lastColor, count, Direction.Clockwise);
        else
            return Range(firstColor, lastColor, count, Direction.CounterClockwise);
    }

    public static IEnumerable<System.Drawing.Color> Range(this System.Drawing.Color firstColor, System.Drawing.Color lastColor, int count, Direction hueDirection)
    {
        var color = firstColor;

        if (count <= 0)
            yield break;

        if (count == 1)
            yield return firstColor;

        float startingHue = color.GetHue();
        float stepHue = GetStepping(firstColor.GetHue(), lastColor.GetHue(), count - 1, hueDirection);
        var stepSaturation = (lastColor.GetSaturation() - firstColor.GetSaturation()) / (count - 1);
        var stepBrightness = (lastColor.GetBrightness() - firstColor.GetBrightness()) / (count - 1);
        var stepAlpha = (lastColor.A - firstColor.A) / (count - 1.0);

        for (int i = 1; i < count; i++)
        {
            yield return color;

            var hueValue = startingHue + stepHue * i;

            if (hueValue > 360)
                hueValue -= 360;

            if (hueValue < 0)
                hueValue = 360 + hueValue;

            color = FromAhsb(
                        Clamp((int)(color.A + stepAlpha), 0, 255),
                             hueValue,
                             Clamp(color.GetSaturation() + stepSaturation, 0, 1),
                             Clamp(color.GetBrightness() + stepBrightness, 0, 1));
        }

        yield return lastColor;
    }

    public enum Direction
    {
        Clockwise = 0,
        CounterClockwise = 1
    }

    private static float GetStepping(float start, float end, int count, Direction direction)
    {
        var hueDiff = end - start;

        switch (direction)
        {
            case Direction.CounterClockwise:
                if (hueDiff >= 0)
                    hueDiff = (360 - hueDiff) * -1;
                break;

            default:
                if (hueDiff <= 0)
                    hueDiff = 360 + hueDiff;
                break;
        }

        return hueDiff / count;
    }

    private static int Clamp(int value, int min, int max)
    {
        if (value < min)
            return min;

        if (value > max)
            return max;

        return value;
    }

    private static float Clamp(float value, float min, float max)
    {
        if (value < min)
            return min;

        if (value > max)
            return max;

        return value;
    }

    public static System.Drawing.Color FromAhsb(int alpha, float hue, float saturation, float brightness)
    {
        if (0 > alpha
            || 255 < alpha)
        {
            throw new ArgumentOutOfRangeException(
                "alpha",
                alpha,
                "Value must be within a range of 0 - 255.");
        }

        if (0f > hue
            || 360f < hue)
        {
            throw new ArgumentOutOfRangeException(
                "hue",
                hue,
                "Value must be within a range of 0 - 360.");
        }

        if (0f > saturation
            || 1f < saturation)
        {
            throw new ArgumentOutOfRangeException(
                "saturation",
                saturation,
                "Value must be within a range of 0 - 1.");
        }

        if (0f > brightness
            || 1f < brightness)
        {
            throw new ArgumentOutOfRangeException(
                "brightness",
                brightness,
                "Value must be within a range of 0 - 1.");
        }

        if (0 == saturation)
        {
            return System.Drawing.Color.FromArgb(
                                alpha,
                                Convert.ToInt32(brightness * 255),
                                Convert.ToInt32(brightness * 255),
                                Convert.ToInt32(brightness * 255));
        }

        float fMax, fMid, fMin;
        int iSextant, iMax, iMid, iMin;

        if (0.5 < brightness)
        {
            fMax = brightness - (brightness * saturation) + saturation;
            fMin = brightness + (brightness * saturation) - saturation;
        }
        else
        {
            fMax = brightness + (brightness * saturation);
            fMin = brightness - (brightness * saturation);
        }

        iSextant = (int)Math.Floor(hue / 60f);
        if (300f <= hue)
        {
            hue -= 360f;
        }

        hue /= 60f;
        hue -= 2f * (float)Math.Floor(((iSextant + 1f) % 6f) / 2f);
        if (0 == iSextant % 2)
        {
            fMid = (hue * (fMax - fMin)) + fMin;
        }
        else
        {
            fMid = fMin - (hue * (fMax - fMin));
        }

        iMax = Convert.ToInt32(fMax * 255);
        iMid = Convert.ToInt32(fMid * 255);
        iMin = Convert.ToInt32(fMin * 255);

        switch (iSextant)
        {
            case 1:
                return System.Drawing.Color.FromArgb(alpha, iMid, iMax, iMin);
            case 2:
                return System.Drawing.Color.FromArgb(alpha, iMin, iMax, iMid);
            case 3:
                return System.Drawing.Color.FromArgb(alpha, iMin, iMid, iMax);
            case 4:
                return System.Drawing.Color.FromArgb(alpha, iMid, iMin, iMax);
            case 5:
                return System.Drawing.Color.FromArgb(alpha, iMax, iMin, iMid);
            default:
                return System.Drawing.Color.FromArgb(alpha, iMax, iMid, iMin);
        }
    }
}
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
  • 1
    The problem is that I've added `System.Drawing` in the references, but when I type `System.` in my code the `Drawing` reference doesn't show up. Are you using this in Wpf or windows form? – Tak Sep 17 '13 at 03:44
  • I am using this in WPF – sa_ddam213 Sep 17 '13 at 03:55
  • Thanks for the answer! Could you please tell me how to apply the example I already wrote in my other question. Where depending on the values of `X` the brush color will change. And I want the change in colotring be smooth as much as possible. So could you please advise? – Tak Sep 17 '13 at 13:28
  • Also, I've went through debugging, but the debug pointer never enters the function `public static IEnumerable Range(this System.Drawing.Color firstColor, System.Drawing.Color lastColor, int count, Direction hueDirection)` although I use step-into, could you please advise how can I enter debug through this function to check the code and understand it? – Tak Sep 18 '13 at 04:01
  • I've used the above answer but with `numberOfIntermediateColors=30` but when I run it, I found different colors rather than red, orange, yellow and green in the results such as blue, purple. I don't know why this is happening? Below snip of my code `IEnumerable colorPalette = System.Drawing.Color.Green.Range(System.Drawing.Color.Red, numberOfIntermediateColors); if (X == 21) Pen = new Pen(new SolidColorBrush(Color.FromArgb(colorPalette.ElementAt(21).A, colorPalette.ElementAt(21).R, colorPalette.ElementAt(21).G, colorPalette.ElementAt(21).B)), 6);`could you please advise? – Tak Sep 18 '13 at 06:13
0

WPF does not care about System.Drawing. Remove that reference from your project.

What you're looking for is a LinearGradientBrush:

<Border>
    <Border.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="Green" Offset="0"/>
            <GradientStop Color="Red" Offset="1"/>
        </LinearGradientBrush>
    </Border.Background>
</Border>

Result:

enter image description here

And please, please, don't use procedural code to define your UI. That's what XAML is for.

Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154
  • 2
    I think OP is trying to create a color palette between 2 colors, not creating a brush. – sa_ddam213 Sep 17 '13 at 02:19
  • @Sa_ddam213 ah, Ok. What do you mean by a color pallette? What would that exactly be? – Federico Berasategui Sep 17 '13 at 02:20
  • 1
    Its just an array of colors http://msdn.microsoft.com/en-us/library/system.drawing.imaging.colorpalette.aspx , I assume OP is missing an extension method from somewhere – sa_ddam213 Sep 17 '13 at 02:22
  • @HighCore Thanks for your answer! What I'm trying to do is to apply the answer found here in WPF http://stackoverflow.com/questions/18821696/use-hsv-instead-of-rgb-in-wpf – Tak Sep 17 '13 at 02:27
  • @HighCore I've updated my question, so if you could please have a look. Many Thanks – Tak Sep 17 '13 at 02:54