-
Notifications
You must be signed in to change notification settings - Fork 53
Expand file tree
/
Copy pathColorRGB.java
More file actions
280 lines (250 loc) · 7.64 KB
/
ColorRGB.java
File metadata and controls
280 lines (250 loc) · 7.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
* #%L
* SciJava Common shared library for SciJava software.
* %%
* Copyright (C) 2009 - 2026 SciJava developers.
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
package org.scijava.util;
import java.io.Serializable;
/**
* A color with red, green and blue color components.
* <p>
* It exists mainly to avoid AWT references to {@link java.awt.Color}.
* </p>
*
* @author Curtis Rueden
* @author Lee Kamentsky
* @author Barry DeZonia
*/
public class ColorRGB implements Serializable {
private static final long serialVersionUID = 1L;
private final int red;
private final int green;
private final int blue;
public ColorRGB(final int red, final int green, final int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
/**
* Parses a color from the given string. The following formats are supported:
* <ol>
* <li>HTML color codes starting with hash ({@code #}), as handled by
* {@link #fromHTMLColor(String)}.</li>
* <li>Color presets, as handled by {@link Colors#getColor(String)}.</li>
* <li>Integer triples of the form {@code r,g,b}, with each element in the
* range {@code [0, 255]}.</li>
* </ol>
*/
public ColorRGB(final String s) {
final ColorRGB result = fromHTMLColor(s);
if (result != null) {
red = result.red;
green = result.green;
blue = result.blue;
}
else {
final String[] tokens = s.split(",");
red = parse(tokens, 0);
green = parse(tokens, 1);
blue = parse(tokens, 2);
}
}
public int getRed() {
return red;
}
public int getGreen() {
return green;
}
public int getBlue() {
return blue;
}
public int getAlpha() {
return 0xff;
}
/**
* Gets the color as a packed integer, 8 bits per color component. HSB is
* alpha, next is red, then green, and finally blue is LSB.
*/
public int getARGB() {
final int a = getAlpha();
final int r = getRed();
final int g = getGreen();
final int b = getBlue();
return (a << 24) | (r << 16) | (g << 8) | b;
}
/**
* Convert this ColorRGB to a string in the format specified by <a
* href="http://www.w3.org/TR/css3-color/">CSS Color Module Level 3 - W3C
* Recommendation 07 June 2011</a>.
* <p>
* We preferentially encode using one of the colors in the table and fall back
* to the hex encoding.
* </p>
*
* @return HTML-encoded string
*/
public String toHTMLColor() {
// return name of matching preset, if possible
final String preset = Colors.getName(this);
if (preset != null) return preset;
// return hex-encoded string
final int r = getRed();
final int g = getGreen();
final int b = getBlue();
return String.format("#%02x%02x%02x", r, g, b);
}
// -- Object methods --
@Override
public String toString() {
return red + "," + green + "," + blue;
}
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof ColorRGB)) return super.equals(obj);
final ColorRGB other = (ColorRGB) obj;
return getRed() == other.getRed() && getGreen() == other.getGreen() &&
getBlue() == other.getBlue() && getAlpha() == other.getAlpha();
}
@Override
public int hashCode() {
return getARGB();
}
// -- Static methods --
/**
* Convert a string in the format specified by <a
* href="http://www.w3.org/TR/css3-color/">CSS Color Module Level 3 - W3C
* Recommendation 07 June 2011</a> to a {@link ColorRGB} object.
*
* @param color The color string to convert.
* @return The resultant color object.
*/
public static ColorRGB fromHTMLColor(final String color) {
// 4.2.1
// The format of an RGB value in hexadecimal notation is a "#"
// immediately followed by either three or six hexadecimal characters.
// The three-digit RGB notation (#rgb) is converted into six-digit form
// (#rrggbb) by replicating digits, not by adding zeros. For example,
// #fb0 expands to #ffbb00. This ensures that white (#ffffff) can be
// specified with the short notation (#fff) and removes any dependencies
// on the color depth of the display.
if (color.startsWith("#")) {
final String hexColor;
if (color.length() == 4) {
hexColor =
new String(new char[] { color.charAt(0), color.charAt(1),
color.charAt(1), color.charAt(2), color.charAt(2),
color.charAt(3), color.charAt(3) });
}
else hexColor = color;
final int red = Integer.parseInt(hexColor.substring(1, 3), 16);
final int green = Integer.parseInt(hexColor.substring(3, 5), 16);
final int blue = Integer.parseInt(hexColor.substring(5, 7), 16);
return new ColorRGB(red, green, blue);
}
// assume color is a preset
return Colors.getColor(color);
}
// TODO - move when we handle color spaces. For now its a convenience method.
public static ColorRGB fromHSVColor(final double h, final double s,
final double v)
{
return hsvToRgb(h, s, v);
}
// -- Helper methods --
private int parse(final String[] s, final int index) {
if (s == null || index >= s.length) return 0;
try {
return Integer.parseInt(s[index]);
}
catch (final NumberFormatException exc) {
return 0;
}
}
/**
* Converts an HSV color value to RGB.
* <p>
* Assumes {@code h}, {@code s}, and {@code v} are contained in the set [0, 1]
* and returns {@code r}, {@code g}, and {@code b} in the set [0, 255].
* </p>
* <p>
* Conversion formula adapted from Wikipedia's <a
* href="http://en.wikipedia.org/wiki/HSL_and_HSV">HSL and HSV article</a> and
* Michael Jackson's <a href="http://bit.ly/9L2qln">blog post on additive
* color model conversion algorithms</a>.
* </p>
*
* @param h The hue
* @param s The saturation
* @param v The value
* @return ColorRGB The RGB representation
*/
private static ColorRGB hsvToRgb(final double h, final double s,
final double v)
{
double r01 = 0, g01 = 0, b01 = 0;
final int i = (int) Math.floor(h * 6);
final double f = h * 6 - i;
final double p = v * (1 - s);
final double q = v * (1 - f * s);
final double t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r01 = v;
g01 = t;
b01 = p;
break;
case 1:
r01 = q;
g01 = v;
b01 = p;
break;
case 2:
r01 = p;
g01 = v;
b01 = t;
break;
case 3:
r01 = p;
g01 = q;
b01 = v;
break;
case 4:
r01 = t;
g01 = p;
b01 = v;
break;
case 5:
r01 = v;
g01 = p;
b01 = q;
break;
}
final int r255 = (int) Math.round(r01 * 255);
final int g255 = (int) Math.round(g01 * 255);
final int b255 = (int) Math.round(b01 * 255);
return new ColorRGB(r255, g255, b255);
}
}