상세 컨텐츠

본문 제목

How to implement a Color Picker by C# in WPF

C#

by 경밤 2020. 6. 28. 11:50

본문

반응형

Index

1. Implement a Spectrum

2. Picking a color by mouse click


In this post, We are going to make a 'Color Picker' with UserControl in WPF.

0. Inital Codes

As you know, In Wpf, there is something very useful control that's LinearGradientBrush and it means that we just only to make a spectrum for picking color.

Let's move on next, to implement a spectrum in code.

<Grid x:Name="SpectrumGrid" Height="40" MouseMove="SpectrumGrid_MouseMove">
	<Rectangle x:Name="SpectrumGridBar" Width="10" HorizontalAlignment="Left" Stroke="Black"></Rectangle>
</Grid>

Code above works like a spectrum slider. SpectrumGrid's background will be filled up by spectrum and SpectrumGridBar will follow our mouse move. 

        public ColorPicker()
        {
            InitializeComponent();

            var g6 = HSV.GradientSpectrum();

            LinearGradientBrush gradientBrush = new LinearGradientBrush();
            gradientBrush.StartPoint = new Point(0, 0);
            gradientBrush.EndPoint = new Point(1, 0);
            for (int i = 0; i < g6.Length; i++) {
                GradientStop stop = new GradientStop(g6[i].Color(), (i) * 0.16);
                gradientBrush.GradientStops.Add(stop);
            }
            SpectrumGrid.Opacity = 1;
            SpectrumGrid.Background = gradientBrush;

            MiddleStop.Color = HSV.RGBFromHSV(0, 1f, 1f).Color();
        }

This is contructor of UserControl. In this code, It initalize GradientBrush and set default GradientStop of color panel.

private void SpectrumGrid_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
	if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
	{
    	var x = e.GetPosition(SpectrumGrid).X;
        pectrumGridBar.Margin = new Thickness(x, 0, 0, 0);
        currH = 360 * (x / this.Width);

        MiddleStop.Color = HSV.RGBFromHSV(currH, 1f, 1f).Color();
	}
}

We will create HSV extension class later. but, We need to know about formula that converts HSV to RGB.

You can reference this post.

1. RGB and HSV classes

    public class RGB
    {
        public byte R { get; set; }
        public byte G { get; set; }
        public byte B { get; set; }
        public RGB() 
        {
            R = 0xff;
            G = 0xff;
            B = 0xff;
        }
        public RGB(double r, double g, double b)
        {
            if (r > 255 || g > 255 || b > 255) throw new Exception("RGB must be under 255 (1byte)");
            R = (byte)r;
            G = (byte)g;
            B = (byte)b;
        }
        public string Hex()
        {
            return BitConverter.ToString(new byte[] { R, G, B }).Replace("-", string.Empty);
        }
        public Color Color()
        {
            var color = new Color();
            color.R = R;
            color.G = G;
            color.B = B;
            color.A = 255;
            return color;
        }
    }

It's class for simplifiy when using in HSV.

    public static class HSV
    {
        public static RGB[] GetSpectrum()
        {
            RGB[] rgbs = new RGB[360];

            for (int h = 0; h < 360; h++)
            {
                rgbs[h] = RGBFromHSV(h, 1f, 1f);
            }
            return rgbs;
        }
        public static RGB[] GradientSpectrum()
        {
            RGB[] rgbs = new RGB[7];

            for (int h = 0; h < 7; h++)
            {
                rgbs[h] = RGBFromHSV(h*60, 1f, 1f);
            }
            return rgbs;
        }
        public static RGB RGBFromHSV(double h, double s, double v)
        {
            if (h > 360 || h < 0 || s > 1 || s < 0 || v > 1 || v < 0)
                return null;

            double c = v * s;
            double x = c *(1 - Math.Abs((h / 60 % 2) - 1));
            double m = v - c;

            double r = 0, g = 0, b = 0;

            if (h < 60)
            {
                r = c;
                g = x;
            }
            else if(h < 120)
            {
                r = x;
                g = c;
            }
            else if(h < 180)
            {
                g = c;
                b = x;
            }
            else if(h < 240)
            {
                g = x;
                b = c;
            }
            else if(h < 300)
            {
                r = x;
                b = c;
            }
            else if(h <= 360)
            {
                r = c;
                b = x;
            }

            return new RGB((r+m)*255, (g + m) * 255, (b + m) * 255);
        }
    }

HSV static class is the main of this post. It's simple that it just implement HSV to RGB.

Anyway we need 7 GradientStop colors and we can get RGB arrays per 60% of 360%.

Okay That's all. We just made a spectrum.

2. Picking Up a Color!

        <Canvas HorizontalAlignment="Stretch" Height="210" MouseMove="RgbGradient_MouseMove">
            <Canvas.Background>
                <LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
                    <GradientStop Color="Black" Offset="1"/>
                    <GradientStop Color="White"/>
                    <GradientStop x:Name="MiddleStop" Color="Red" Offset="0.5"/>
                </LinearGradientBrush>
            </Canvas.Background>
        </Canvas>

We should one more xaml code. It is used for picking up and let's implement RgbGradient_MousMove.

        private void RgbGradient_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if(e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
            {
                var pos = e.GetPosition(sender as Canvas);
                var x = pos.X;
                var y = pos.Y;
                RGB c; 
                if (x < Width / 2)
                {
                    c = HSV.RGBFromHSV(currH, 1f, x / (Width / 2));
                }
                else
                {
                    c = HSV.RGBFromHSV(currH, (Width / 2 - (x - Width / 2)) / Width, 1f);
                }
                //hexcode = c.Hex(); ....
            }
            
        }

That's all. As you can find, the gradient looks [black - spectrum selected - white], so the S of HSV must be 0 to 100%. It means range of S value is [spectrum color - white] and V is[black - spectrum color].

Finally we made it.

Thank you

반응형

관련글 더보기