~mantas/pinta/stable

« back to all changes in this revision

Viewing changes to Pinta.Core/Effects/HsvColor.cs

  • Committer: Iain Lane
  • Date: 2010-02-19 15:33:30 UTC
  • Revision ID: git-v1:92cc09614a4e2801bfe39cd971f6b31e694a500b
ImportedĀ UpstreamĀ versionĀ 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////////
 
2
// Paint.NET                                                                   //
 
3
// Copyright (C) Rick Brewster, Tom Jackson, and past contributors.            //
 
4
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.          //
 
5
// See src/Resources/Files/License.txt for full licensing and attribution      //
 
6
// details.                                                                    //
 
7
// .                                                                           //
 
8
/////////////////////////////////////////////////////////////////////////////////
 
9
 
 
10
using System;
 
11
 
 
12
namespace Pinta.Core
 
13
{
 
14
    /// <summary>
 
15
    /// Adapted from: 
 
16
    /// "A Primer on Building a Color Picker User Control with GDI+ in Visual Basic .NET or C#"
 
17
    /// http://www.msdnaa.net/Resources/display.aspx?ResID=2460
 
18
    /// </summary>
 
19
    public struct HsvColor
 
20
    {
 
21
        public int Hue; // 0-360
 
22
        public int Saturation; // 0-100
 
23
        public int Value; // 0-100
 
24
 
 
25
        public static bool operator== (HsvColor lhs, HsvColor rhs)
 
26
        {
 
27
            if ((lhs.Hue == rhs.Hue) &&
 
28
                (lhs.Saturation == rhs.Saturation) &&
 
29
                (lhs.Value == rhs.Value))
 
30
            {
 
31
                return true;
 
32
            }
 
33
            else
 
34
            {
 
35
                return false;
 
36
            }
 
37
        }
 
38
 
 
39
        public static bool operator!= (HsvColor lhs, HsvColor rhs)
 
40
        {
 
41
            return !(lhs == rhs);
 
42
        }
 
43
 
 
44
        public override bool Equals(object obj)
 
45
        {
 
46
            return this == (HsvColor)obj;
 
47
        }
 
48
 
 
49
        public override int GetHashCode()
 
50
        {
 
51
            return (Hue + (Saturation << 8) + (Value << 16)).GetHashCode();;
 
52
        }
 
53
 
 
54
        public HsvColor(int hue, int saturation, int value) 
 
55
        {
 
56
            if (hue < 0 || hue > 360)
 
57
            {
 
58
                throw new ArgumentOutOfRangeException("hue", "must be in the range [0, 360]");
 
59
            }
 
60
 
 
61
            if (saturation < 0 || saturation > 100)
 
62
            {
 
63
                throw new ArgumentOutOfRangeException("saturation", "must be in the range [0, 100]");
 
64
            }
 
65
 
 
66
            if (value < 0 || value > 100)
 
67
            {
 
68
                throw new ArgumentOutOfRangeException("value", "must be in the range [0, 100]");
 
69
            }
 
70
 
 
71
            Hue = hue;
 
72
            Saturation = saturation;
 
73
            Value = value;
 
74
        }
 
75
 
 
76
//        public static HsvColor FromColor(Color color)
 
77
//        {
 
78
//            RgbColor rgb = new RgbColor(color.R, color.G, color.B);
 
79
//            return rgb.ToHsv();
 
80
//        }
 
81
//
 
82
//        public Color ToColor()
 
83
//        {
 
84
//            RgbColor rgb = ToRgb();
 
85
//            return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
 
86
//        }
 
87
 
 
88
        public RgbColor ToRgb() 
 
89
        {
 
90
            // HsvColor contains values scaled as in the color wheel:
 
91
 
 
92
            double h;
 
93
            double s;
 
94
            double v;
 
95
 
 
96
            double r = 0;
 
97
            double g = 0;
 
98
            double b = 0;
 
99
 
 
100
            // Scale Hue to be between 0 and 360. Saturation
 
101
            // and value scale to be between 0 and 1.
 
102
            h = (double) Hue % 360;
 
103
            s = (double) Saturation / 100;
 
104
            v = (double) Value / 100;
 
105
 
 
106
            if (s == 0)
 
107
            {
 
108
                // If s is 0, all colors are the same.
 
109
                // This is some flavor of gray.
 
110
                r = v;
 
111
                g = v;
 
112
                b = v;
 
113
            } 
 
114
            else 
 
115
            {
 
116
                double p;
 
117
                double q;
 
118
                double t;
 
119
 
 
120
                double fractionalSector;
 
121
                int sectorNumber;
 
122
                double sectorPos;
 
123
 
 
124
                // The color wheel consists of 6 sectors.
 
125
                // Figure out which sector you're in.
 
126
                sectorPos = h / 60;
 
127
                sectorNumber = (int)(Math.Floor(sectorPos));
 
128
 
 
129
                // get the fractional part of the sector.
 
130
                // That is, how many degrees into the sector
 
131
                // are you?
 
132
                fractionalSector = sectorPos - sectorNumber;
 
133
 
 
134
                // Calculate values for the three axes
 
135
                // of the color. 
 
136
                p = v * (1 - s);
 
137
                q = v * (1 - (s * fractionalSector));
 
138
                t = v * (1 - (s * (1 - fractionalSector)));
 
139
 
 
140
                // Assign the fractional colors to r, g, and b
 
141
                // based on the sector the angle is in.
 
142
                switch (sectorNumber) 
 
143
                {
 
144
                    case 0:
 
145
                        r = v;
 
146
                        g = t;
 
147
                        b = p;
 
148
                        break;
 
149
 
 
150
                    case 1:
 
151
                        r = q;
 
152
                        g = v;
 
153
                        b = p;
 
154
                        break;
 
155
 
 
156
                    case 2:
 
157
                        r = p;
 
158
                        g = v;
 
159
                        b = t;
 
160
                        break;
 
161
 
 
162
                    case 3:
 
163
                        r = p;
 
164
                        g = q;
 
165
                        b = v;
 
166
                        break;
 
167
 
 
168
                    case 4:
 
169
                        r = t;
 
170
                        g = p;
 
171
                        b = v;
 
172
                        break;
 
173
 
 
174
                    case 5:
 
175
                        r = v;
 
176
                        g = p;
 
177
                        b = q;
 
178
                        break;
 
179
                }
 
180
            }
 
181
            // return an RgbColor structure, with values scaled
 
182
            // to be between 0 and 255.
 
183
            return new RgbColor((int)(r * 255), (int)(g * 255), (int)(b * 255));
 
184
        }
 
185
 
 
186
        public override string ToString() 
 
187
        {
 
188
            return String.Format("({0}, {1}, {2})", Hue, Saturation, Value);
 
189
        }
 
190
    }
 
191
}