~ubuntu-branches/debian/stretch/insubstantial/stretch

« back to all changes in this revision

Viewing changes to substance/src/main/java/org/pushingpixels/substance/internal/contrib/xoetrope/editor/color/ModelColor.java

  • Committer: Package Import Robot
  • Author(s): Felix Natter
  • Date: 2016-01-18 20:58:45 UTC
  • Revision ID: package-import@ubuntu.com-20160118205845-crbmrkda61qsi5qa
Tags: upstream-7.3+dfsg2
ImportĀ upstreamĀ versionĀ 7.3+dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.pushingpixels.substance.internal.contrib.xoetrope.editor.color;
 
2
 
 
3
import java.awt.Color;
 
4
 
 
5
/**
 
6
 * A RYB Color model $Revision: 2254 $
 
7
 */
 
8
public class ModelColor {
 
9
        public static final int NUM_COLOR_RINGS = 7;
 
10
        public static final int NUM_SEGMENTS = 24;
 
11
        protected boolean webSnap = false;
 
12
 
 
13
        private static ModelColor[][] baseColors;
 
14
 
 
15
        protected int R, G, B;
 
16
        protected double H, S, V;
 
17
        protected double rgbMinValue, rgbMaxValue;
 
18
 
 
19
        public static double[] SATURATION_BANDS = { 0.4, 0.6, 0.8, 1.0, 1.0, 1.0,
 
20
                        1.0 };
 
21
        public static double[] BRIGHTNESS_BANDS = { 1.0, 1.0, 1.0, 1.0, 1.0, 0.85,
 
22
                        0.65, 0.45 };
 
23
 
 
24
        /**
 
25
         * Create a new ModelColor
 
26
         * 
 
27
         * @param R
 
28
         *            the red value in the range 0-255
 
29
         * @param G
 
30
         *            the green value in the range 0-255
 
31
         * @param B
 
32
         *            the blue value in the range 0-255
 
33
         */
 
34
        public ModelColor(int R, int G, int B) {
 
35
                this(R, G, B, -1);
 
36
        }
 
37
 
 
38
        public ModelColor(double H, double S, double V) {
 
39
                setHSV(H, S, V);
 
40
        }
 
41
 
 
42
        /**
 
43
         * Create a new ModelColor
 
44
         * 
 
45
         * @param R
 
46
         *            the red value in the range 0-255
 
47
         * @param G
 
48
         *            the green value in the range 0-255
 
49
         * @param B
 
50
         *            the blue value in the range 0-255
 
51
         * @param H
 
52
         *            the hue value in the range 0-255
 
53
         */
 
54
        public ModelColor(int R, int G, int B, int H) {
 
55
                initColorWheel();
 
56
                setRGB(R, G, B, H);
 
57
        }
 
58
 
 
59
        /**
 
60
         * Creates a copy of an ModelColor
 
61
         * 
 
62
         * @param c
 
63
         *            the ModelColor to copy
 
64
         */
 
65
        public ModelColor(ModelColor c) {
 
66
                initColorWheel();
 
67
                R = c.R;
 
68
                G = c.G;
 
69
                B = c.B;
 
70
 
 
71
                H = c.H;
 
72
                S = c.S;
 
73
                V = c.V;
 
74
                getRgbMinMaxValues();
 
75
        }
 
76
 
 
77
        /**
 
78
         * Get the red value
 
79
         * 
 
80
         * @return the red value in the range 0-255
 
81
         */
 
82
        public int getRed() {
 
83
                return R;
 
84
        }
 
85
 
 
86
        /**
 
87
         * Get the green value
 
88
         * 
 
89
         * @return the green value in the range 0-255
 
90
         */
 
91
        public int getGreen() {
 
92
                return G;
 
93
        }
 
94
 
 
95
        /**
 
96
         * Get the blue value
 
97
         * 
 
98
         * @return the blue value in the range 0-255
 
99
         */
 
100
        public int getBlue() {
 
101
                return B;
 
102
        }
 
103
 
 
104
        /**
 
105
         * Get the hue value
 
106
         * 
 
107
         * @return the hue value in the range 0-255
 
108
         */
 
109
        public int getHue() {
 
110
                return (int) Math.floor(H + 0.5);
 
111
        }
 
112
 
 
113
        /**
 
114
         * Get the hue value
 
115
         * 
 
116
         * @return the hue value in the range 0-255
 
117
         */
 
118
        public double getH() {
 
119
                return H;
 
120
        }
 
121
 
 
122
        /**
 
123
         * Get the saturation value
 
124
         * 
 
125
         * @return the saturation value in the range 0.0-1.0
 
126
         */
 
127
        public double getSaturation() {
 
128
                return S;
 
129
        }
 
130
 
 
131
        /**
 
132
         * Get the brightness value
 
133
         * 
 
134
         * @return the brightness value in the range 0.0-1.0
 
135
         */
 
136
        public double getBrightness() {
 
137
                return V;
 
138
        }
 
139
 
 
140
        /**
 
141
         * Set an RGB color
 
142
         * 
 
143
         * @param R
 
144
         *            the red value in the range 0-255
 
145
         * @param G
 
146
         *            the green value in the range 0-255
 
147
         * @param B
 
148
         *            the blue value in the range 0-255
 
149
         */
 
150
        public void setRGB(int R, int G, int B) {
 
151
                setRGB(R, G, B, -1);
 
152
        }
 
153
 
 
154
        /**
 
155
         * Set an RGB color
 
156
         * 
 
157
         * @param r
 
158
         *            the red value in the range 0-255
 
159
         * @param g
 
160
         *            the green value in the range 0-255
 
161
         * @param b
 
162
         *            the blue value in the range 0-255
 
163
         * @param h
 
164
         *            the hue value in the range 0-255
 
165
         */
 
166
        public void setRGB(int r, int g, int b, int h) {
 
167
                if (webSnap) {
 
168
                        R = Math.round(r / 51) * 51;
 
169
                        G = Math.round(g / 51) * 51;
 
170
                        B = Math.round(b / 51) * 51;
 
171
                } else {
 
172
                        R = r;
 
173
                        G = g;
 
174
                        B = b;
 
175
                }
 
176
 
 
177
                checkRange();
 
178
                getRgbMinMaxValues();
 
179
                if (h > -1) {
 
180
                        H = h;
 
181
                        S = (rgbMaxValue > 0) ? (rgbMaxValue - rgbMinValue) / rgbMaxValue
 
182
                                        : 0;
 
183
                        V = rgbMaxValue / 255;
 
184
                } else if ((R == G) && (G == B)) {
 
185
                        H = 0;
 
186
                        S = 0;
 
187
                        V = rgbMaxValue / 255;
 
188
                } else
 
189
                        calculateHSVfromRGB();
 
190
        }
 
191
 
 
192
        /**
 
193
         * Set the color to a HSV value
 
194
         * 
 
195
         * @param _h
 
196
         *            the hue
 
197
         * @param _s
 
198
         *            the saturation
 
199
         * @param _v
 
200
         *            the value
 
201
         */
 
202
        public void setHSV(double _h, double _s, double _v) {
 
203
                if (Math.abs(H - _h) > 0.499999)
 
204
                        H = _h;
 
205
                if (Math.abs(S - _s) > 0.009999)
 
206
                        S = _s;
 
207
                if (Math.abs(V - _v) > 0.009999)
 
208
                        V = _v;
 
209
 
 
210
                if ((S > 1.0) || (S < 0.0))
 
211
                        S = (S < 0.0) ? 0.0 : 1.0;
 
212
                if ((V > 1.0) || (V < 0.0))
 
213
                        V = (V < 0.0) ? 0.0 : 1.0;
 
214
 
 
215
                calculateRGBfromHSV();
 
216
        }
 
217
 
 
218
        /**
 
219
         * Check that the RGB values are in range
 
220
         */
 
221
        private void checkRange() {
 
222
                if (R > 255)
 
223
                        R = 255;
 
224
                if (G > 255)
 
225
                        G = 255;
 
226
                if (B > 255)
 
227
                        B = 255;
 
228
 
 
229
                if (webSnap) {
 
230
                        R = Math.round(R / 51) * 51;
 
231
                        G = Math.round(G / 51) * 51;
 
232
                        B = Math.round(B / 51) * 51;
 
233
                }
 
234
        }
 
235
 
 
236
        /**
 
237
         * Get the minimum and maximum of the RGB values.
 
238
         */
 
239
        private void getRgbMinMaxValues() {
 
240
                rgbMaxValue = Math.max(Math.max(R, G), B);
 
241
                rgbMinValue = Math.min(Math.min(R, G), B);
 
242
        }
 
243
 
 
244
        private void calculateHSVfromRGB() {
 
245
                // Find the two base colors
 
246
                boolean exactMatch = false;
 
247
                outer: for (int j = 0; j < NUM_COLOR_RINGS; j++) {
 
248
                        if (j == 6)
 
249
                                j = 6;
 
250
                        for (int i = 0; i < 360; i += 15) {
 
251
                                ModelColor c = baseColors[i / 15][j];
 
252
                                if ((R == c.R) && (G == c.G) && (B == c.B)) {
 
253
                                        exactMatch = true;
 
254
                                        H = c.H;
 
255
                                        S = (rgbMaxValue > 0) ? 1.0 * (rgbMaxValue - rgbMinValue)
 
256
                                                        / rgbMaxValue : 0.0;
 
257
                                        V = rgbMaxValue / 255.0;
 
258
                                        break outer;
 
259
                                }
 
260
                        }
 
261
                }
 
262
 
 
263
                if (!exactMatch) {
 
264
                        // Red-Green-Blue to Red-Yellow-Blue
 
265
                        // degrees
 
266
                        // R = 0 R = 0
 
267
                        // Y = 60 Y = 120
 
268
                        // G = 120 G = 180
 
269
                        // B == 240 B = 240
 
270
                        // Fractional values = degrees / 360.0
 
271
                        float values[] = new float[3];
 
272
                        values = Color.RGBtoHSB(R, G, B, values);
 
273
                        float h = values[0];
 
274
                        S = (rgbMaxValue > 0) ? 1.0 * (rgbMaxValue - rgbMinValue)
 
275
                                        / rgbMaxValue : 0.0;
 
276
                        V = rgbMaxValue / 255.0;
 
277
                        if (h < 0.1666668f)
 
278
                                h *= 2.0f;
 
279
                        else if (h < 0.3333334f)
 
280
                                h += 0.1666667f;
 
281
                        else if (h < 0.6666668f)
 
282
                                h = h + 0.1666667f * ((0.6666667f - h) / 0.3333334f);
 
283
                        H = 360.0 * h;
 
284
                }
 
285
        }
 
286
 
 
287
        private void calculateRGBfromHSV() {
 
288
                // Red-Green-Blue to Red-Yellow-Blue
 
289
                // degrees degrees
 
290
                // R = 0 R = 0
 
291
                // Y = 60 Y = 120
 
292
                // G = 120 G = 180
 
293
                // B == 240 B = 240
 
294
                // Fractional values = degrees / 360.0
 
295
                double h = H / 360.0;
 
296
                if (h < 0.3333334)
 
297
                        h /= 2.0;
 
298
                else if (h < 0.5000001)
 
299
                        h -= 0.1666667;
 
300
                else if (h < 0.6666668)
 
301
                        h = 2.0 * h - 0.6666667;
 
302
 
 
303
                Color c = new Color(Color.HSBtoRGB((float) h, (float) S, (float) V));
 
304
                R = c.getRed();
 
305
                G = c.getGreen();
 
306
                B = c.getBlue();
 
307
 
 
308
                checkRange();
 
309
                getRgbMinMaxValues();
 
310
        }
 
311
 
 
312
        /**
 
313
         * Rotate this color by a specified amount
 
314
         * 
 
315
         * @param angle
 
316
         *            the angle by which to move this color (hue)
 
317
         */
 
318
        public void rotate(int angle) {
 
319
                if ((S > 0) && (V > 0)) {
 
320
                        double newHue = (H + angle) % 360.0;
 
321
                        setHSV(newHue, S, V);// S * S1 / S2, V * V1 / V2 );
 
322
                }
 
323
        }
 
324
 
 
325
        /**
 
326
         * Set the snap to web colors setting
 
327
         * 
 
328
         * @param snapTo
 
329
         *            true to snap to web colors
 
330
         */
 
331
        public void setWebSnap(boolean snapTo) {
 
332
                webSnap = snapTo;
 
333
        }
 
334
 
 
335
        /**
 
336
         * Convert a decimal rgb value to a hexadecimal value
 
337
         * 
 
338
         * @param n
 
339
         *            the decimal value
 
340
         * @return the hex value
 
341
         */
 
342
        public static String dec2hex(int n) {
 
343
                String s = Integer.toHexString(n);
 
344
                if (s.length() < 2)
 
345
                        s = "0" + s;
 
346
                return s.toUpperCase();
 
347
        }
 
348
 
 
349
        /**
 
350
         * Convert a hexadecimal rgb value to a decimal value
 
351
         * 
 
352
         * @param n
 
353
         *            the hex value
 
354
         * @return the decimal value
 
355
         */
 
356
        public static int hex2dec(String n) {
 
357
                if (n.length() == 0)
 
358
                        return 0;
 
359
                return Integer.parseInt(n, 16);
 
360
        }
 
361
 
 
362
        /**
 
363
         * Get a two letter hex string for the decimal value in the range 0-255
 
364
         */
 
365
        public static String toHexString(int value) {
 
366
                String hex = Integer.toHexString(value).toUpperCase();
 
367
                if (hex.length() < 2)
 
368
                        return "0" + hex;
 
369
 
 
370
                return hex;
 
371
        }
 
372
 
 
373
        /**
 
374
         * Get a grayscale hex value for an rgb color
 
375
         * 
 
376
         * @param r
 
377
         *            the red value
 
378
         * @param g
 
379
         *            the green value
 
380
         * @param b
 
381
         *            the blue value
 
382
         * @return the hex value
 
383
         */
 
384
        public static String col2Gray(double r, double g, double b) {
 
385
                double lum = Math.round(r * 0.299 + g * 0.587 + b * 0.114);
 
386
                return dec2hex((int) lum) + dec2hex((int) lum) + dec2hex((int) lum);
 
387
        }
 
388
 
 
389
        public static ModelColor[][] getBaseColors() {
 
390
                initColorWheel();
 
391
                return baseColors;
 
392
        }
 
393
 
 
394
        private static void initColorWheel() {
 
395
                if (baseColors == null) {
 
396
                        baseColors = new ModelColor[24][NUM_COLOR_RINGS];
 
397
 
 
398
                        int idx = 0;
 
399
                        for (int i = 0; i < NUM_COLOR_RINGS; i++) {
 
400
                                for (int j = 0; j < 24; j++) {
 
401
                                        baseColors[j][i] = new ModelColor(15.0 * j,
 
402
                                                        SATURATION_BANDS[i], BRIGHTNESS_BANDS[i + 1
 
403
                                                                        - (j % 2)]);
 
404
                                        idx++;
 
405
                                }
 
406
                        }
 
407
                }
 
408
        }
 
409
}