1
package org.pushingpixels.substance.internal.contrib.xoetrope.editor.color;
6
* A RYB Color model $Revision: 2254 $
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;
13
private static ModelColor[][] baseColors;
15
protected int R, G, B;
16
protected double H, S, V;
17
protected double rgbMinValue, rgbMaxValue;
19
public static double[] SATURATION_BANDS = { 0.4, 0.6, 0.8, 1.0, 1.0, 1.0,
21
public static double[] BRIGHTNESS_BANDS = { 1.0, 1.0, 1.0, 1.0, 1.0, 0.85,
25
* Create a new ModelColor
28
* the red value in the range 0-255
30
* the green value in the range 0-255
32
* the blue value in the range 0-255
34
public ModelColor(int R, int G, int B) {
38
public ModelColor(double H, double S, double V) {
43
* Create a new ModelColor
46
* the red value in the range 0-255
48
* the green value in the range 0-255
50
* the blue value in the range 0-255
52
* the hue value in the range 0-255
54
public ModelColor(int R, int G, int B, int H) {
60
* Creates a copy of an ModelColor
63
* the ModelColor to copy
65
public ModelColor(ModelColor c) {
80
* @return the red value in the range 0-255
89
* @return the green value in the range 0-255
91
public int getGreen() {
98
* @return the blue value in the range 0-255
100
public int getBlue() {
107
* @return the hue value in the range 0-255
109
public int getHue() {
110
return (int) Math.floor(H + 0.5);
116
* @return the hue value in the range 0-255
118
public double getH() {
123
* Get the saturation value
125
* @return the saturation value in the range 0.0-1.0
127
public double getSaturation() {
132
* Get the brightness value
134
* @return the brightness value in the range 0.0-1.0
136
public double getBrightness() {
144
* the red value in the range 0-255
146
* the green value in the range 0-255
148
* the blue value in the range 0-255
150
public void setRGB(int R, int G, int B) {
158
* the red value in the range 0-255
160
* the green value in the range 0-255
162
* the blue value in the range 0-255
164
* the hue value in the range 0-255
166
public void setRGB(int r, int g, int b, int h) {
168
R = Math.round(r / 51) * 51;
169
G = Math.round(g / 51) * 51;
170
B = Math.round(b / 51) * 51;
178
getRgbMinMaxValues();
181
S = (rgbMaxValue > 0) ? (rgbMaxValue - rgbMinValue) / rgbMaxValue
183
V = rgbMaxValue / 255;
184
} else if ((R == G) && (G == B)) {
187
V = rgbMaxValue / 255;
189
calculateHSVfromRGB();
193
* Set the color to a HSV value
202
public void setHSV(double _h, double _s, double _v) {
203
if (Math.abs(H - _h) > 0.499999)
205
if (Math.abs(S - _s) > 0.009999)
207
if (Math.abs(V - _v) > 0.009999)
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;
215
calculateRGBfromHSV();
219
* Check that the RGB values are in range
221
private void checkRange() {
230
R = Math.round(R / 51) * 51;
231
G = Math.round(G / 51) * 51;
232
B = Math.round(B / 51) * 51;
237
* Get the minimum and maximum of the RGB values.
239
private void getRgbMinMaxValues() {
240
rgbMaxValue = Math.max(Math.max(R, G), B);
241
rgbMinValue = Math.min(Math.min(R, G), B);
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++) {
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)) {
255
S = (rgbMaxValue > 0) ? 1.0 * (rgbMaxValue - rgbMinValue)
257
V = rgbMaxValue / 255.0;
264
// Red-Green-Blue to Red-Yellow-Blue
270
// Fractional values = degrees / 360.0
271
float values[] = new float[3];
272
values = Color.RGBtoHSB(R, G, B, values);
274
S = (rgbMaxValue > 0) ? 1.0 * (rgbMaxValue - rgbMinValue)
276
V = rgbMaxValue / 255.0;
279
else if (h < 0.3333334f)
281
else if (h < 0.6666668f)
282
h = h + 0.1666667f * ((0.6666667f - h) / 0.3333334f);
287
private void calculateRGBfromHSV() {
288
// Red-Green-Blue to Red-Yellow-Blue
294
// Fractional values = degrees / 360.0
295
double h = H / 360.0;
298
else if (h < 0.5000001)
300
else if (h < 0.6666668)
301
h = 2.0 * h - 0.6666667;
303
Color c = new Color(Color.HSBtoRGB((float) h, (float) S, (float) V));
309
getRgbMinMaxValues();
313
* Rotate this color by a specified amount
316
* the angle by which to move this color (hue)
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 );
326
* Set the snap to web colors setting
329
* true to snap to web colors
331
public void setWebSnap(boolean snapTo) {
336
* Convert a decimal rgb value to a hexadecimal value
340
* @return the hex value
342
public static String dec2hex(int n) {
343
String s = Integer.toHexString(n);
346
return s.toUpperCase();
350
* Convert a hexadecimal rgb value to a decimal value
354
* @return the decimal value
356
public static int hex2dec(String n) {
359
return Integer.parseInt(n, 16);
363
* Get a two letter hex string for the decimal value in the range 0-255
365
public static String toHexString(int value) {
366
String hex = Integer.toHexString(value).toUpperCase();
367
if (hex.length() < 2)
374
* Get a grayscale hex value for an rgb color
382
* @return the hex value
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);
389
public static ModelColor[][] getBaseColors() {
394
private static void initColorWheel() {
395
if (baseColors == null) {
396
baseColors = new ModelColor[24][NUM_COLOR_RINGS];
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