001: /*
002: This file is part of LayoutHelper - Utilities for LayoutManagment
003: Copyright (c) 2004 Patrick Gotthardt
004:
005: This program is free software; you can redistribute it and/or
006: modify it under the terms of the GNU General Public License
007: as published by the Free Software Foundation; either version 2
008: of the License, or any later version.
009:
010: This program is distributed in the hope that it will be useful,
011: but WITHOUT ANY WARRANTY; without even the implied warranty of
012: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: GNU General Public License for more details.
014:
015: You should have received a copy of the GNU General Public License
016: along with this program; if not, write to the Free Software
017: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019: package com.pagosoft.swing;
020:
021: import java.awt.*;
022: import java.util.List;
023: import java.util.ArrayList;
024: import java.util.Map;
025: import java.util.TreeMap;
026:
027: public class ColorUtils {
028: /*
029: public static List<Color> gradient(Color a, Color t, int precision) {
030: int r = t.getRed() - a.getRed();
031: int g = t.getGreen() - a.getGreen();
032: int b = t.getBlue() - a.getBlue();
033: int al = t.getAlpha() - a.getAlpha();
034: ArrayList<Color> colors = new ArrayList<Color>();
035: for(int i = 1; i < precision+1; i++) {
036: System.out.printf("Color:%nRed: %s%nGreen: %s%nBlue: %s%n%n",
037: (r/(i/precision))+a.getRed(),
038: (g/(i/precision))+a.getGreen(),
039: (b/(i/precision))+a.getBlue());
040: colors.add(new Color(
041: (r/(i/precision))+a.getRed(),
042: (g/(i/precision))+a.getGreen(),
043: (b/(i/precision))+a.getBlue(),
044: (al/(i/precision))+a.getAlpha()));
045: }
046: return colors;
047: }*/
048:
049: /**
050: * Can be:
051: * (255, 0, 0)
052: * 255, 0, 0
053: * #FF0000
054: * #F00
055: * red
056: */
057: public static Color toColor(String str) {
058: switch (str.charAt(0)) {
059: case '(':
060: int red,
061: green,
062: blue;
063: int index;
064:
065: red = nextColorInt(str, 1);
066:
067: index = str.indexOf(',');
068: green = nextColorInt(str, index + 1);
069:
070: index = str.indexOf(',', index + 1);
071: blue = nextColorInt(str, index + 1);
072:
073: return new Color(red, green, blue);
074: case '#':
075: // Shorthand?
076: if (str.length() == 4) {
077: return new Color(getShorthandValue(str.charAt(1)),
078: getShorthandValue(str.charAt(2)),
079: getShorthandValue(str.charAt(3)));
080: } else {
081: return new Color(Integer.parseInt(str.substring(1), 16));
082: }
083: default:
084: if (Character.isDigit(str.charAt(0))) {
085: red = nextColorInt(str, 0);
086:
087: index = str.indexOf(',');
088: green = nextColorInt(str, index + 1);
089:
090: index = str.indexOf(',', index + 1);
091: blue = nextColorInt(str, index + 1);
092:
093: return new Color(red, green, blue);
094: }
095: return (Color) colorNamesMap.get(str);
096: }
097: }
098:
099: private static int nextColorInt(String str, int index) {
100: // start with adjusting the start index
101: while (index < str.length()) {
102: char c = str.charAt(index);
103: // a digit?
104: if ('0' <= c && c <= '9') {
105: break;
106: } else {
107: index++;
108: }
109: }
110: // that's only the maximum limit!
111: int colorLength = index;
112: for (; colorLength < index + 3; colorLength++) {
113: char c = str.charAt(colorLength);
114: // not a digit?
115: if (c < '0' || '9' < c) {
116: break;
117: }
118: }
119: return Integer.parseInt(str.substring(index, colorLength));
120: }
121:
122: private static int getShorthandValue(char c) {
123: c = Character.toUpperCase(c);
124: if ('A' <= c && c <= 'F') {
125: return colorShorthandTable[c - 'A' + 10];
126: }
127: return colorShorthandTable[c - '0'];
128: }
129:
130: private static int[] colorShorthandTable = { 0x00, 0x11, 0x22,
131: 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC,
132: 0xDD, 0xEE, 0xFF };
133:
134: private static Map colorNamesMap;
135:
136: static {
137: colorNamesMap = new TreeMap();
138: colorNamesMap.put("white", new Color(0xFFFFFF));
139: colorNamesMap.put("lightGray", new Color(0xC0C0C0));
140: colorNamesMap.put("gray", new Color(0x808080));
141: colorNamesMap.put("darkGray", new Color(0x404040));
142: colorNamesMap.put("black", new Color(0x000000));
143: colorNamesMap.put("red", new Color(0xFF0000));
144: colorNamesMap.put("pink", new Color(0xFFAFAF));
145: colorNamesMap.put("orange", new Color(0xFFC800));
146: colorNamesMap.put("yellow", new Color(0xFFFF00));
147: colorNamesMap.put("green", new Color(0x00FF00));
148: colorNamesMap.put("magenta", new Color(0xFF00FF));
149: colorNamesMap.put("cyan", new Color(0x00FFFF));
150: colorNamesMap.put("blue", new Color(0x0000FF));
151: }
152:
153: public static Color oposite(Color a) {
154: return new Color(255 - a.getRed(), 255 - a.getGreen(), 255 - a
155: .getBlue(), a.getAlpha());
156: }
157:
158: public static Color subtract(Color a, Color b) {
159: return new Color(Math.max(0, Math.min(255, a.getRed()
160: - b.getRed())), Math.max(0, Math.min(255, a.getGreen()
161: - b.getGreen())), Math.max(0, Math.min(255, a.getBlue()
162: - b.getBlue())));
163: }
164:
165: public static String toString(Color c) {
166: String colString = Integer.toHexString(c.getRGB() & 0xffffff)
167: .toUpperCase();
168: return "#000000".substring(0, 7 - colString.length()).concat(
169: colString);
170: }
171:
172: public static Color getTranslucentColor(Color c, int alpha) {
173: return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha);
174: }
175:
176: public static Color getSimiliarColor(Color color, float factor) {
177: return new Color(between((int) (color.getRed() * factor), 0,
178: 255),
179: between((int) (color.getGreen() * factor), 0, 255),
180: between((int) (color.getBlue() * factor), 0, 255),
181: color.getAlpha());
182: }
183:
184: private static int between(int v, int min, int max) {
185: return Math.max(min, Math.min(v, max));
186: }
187:
188: public static Color getColor(Color color, float factor) {
189: float[] hsbValues = new float[3];
190: Color.RGBtoHSB(color.getRed(), color.getGreen(), color
191: .getBlue(), hsbValues);
192: return Color.getHSBColor(hsbValues[0], hsbValues[1],
193: hsbValues[2] * factor);
194: }
195:
196: /**
197: * <p>Returns an array of 9 colors which one could use very good together.</p>
198: * <p>The code to calculate the colors is taken from Twyst <http://www.colormixers.com/>.<br />
199: * I've just translated it into Java.</p>
200: *
201: * @author Twyst, Patrick Gotthardt
202: * @param c The base Color (returned as index 0)
203: * @return An Array of colors which are harmonic to the base color.
204: */
205: public static Color[] mixColors(Color c) {
206: Color[] result = new Color[9];
207:
208: result[0] = c;
209:
210: double[] hs = RGBtoHSV(c);
211: double[] y = new double[3];
212: double[] yx = new double[3];
213: double[] p = new double[3];
214: double[] pr = new double[3];
215:
216: // First two
217: p[0] = y[0] = hs[0];
218: p[1] = y[1] = hs[1];
219:
220: if (hs[2] > 70) {
221: y[2] = hs[2] - 30;
222: p[2] = hs[2] - 15;
223: } else {
224: y[2] = hs[2] + 30;
225: p[2] = hs[2] + 15;
226: }
227:
228: result[1] = HSVtoRGB(p);
229: result[2] = HSVtoRGB(y);
230:
231: // Second three
232: if (hs[0] >= 0 && hs[0] < 30) {
233: pr[0] = yx[0] = y[0] = hs[0] + 20;
234: pr[1] = yx[1] = y[1] = hs[1];
235: y[2] = hs[2];
236:
237: if (hs[2] > 70) {
238: yx[2] = hs[2] - 30;
239: pr[2] = hs[2] - 15;
240: } else {
241: yx[2] = hs[2] + 30;
242: pr[2] = hs[2] + 15;
243: }
244: }
245: if (hs[0] >= 30 && hs[0] < 60) {
246: pr[0] = yx[0] = y[0] = hs[0] + 150;
247: y[1] = minMax(hs[1] - 30, 0, 100);
248: y[2] = minMax(hs[2] - 20, 0, 100);
249:
250: pr[1] = yx[1] = minMax(hs[1] - 70, 0, 100);
251: yx[2] = minMax(hs[2] + 20, 0, 100);
252: pr[2] = hs[2];
253: }
254: if (hs[0] >= 60 && hs[0] < 180) {
255: pr[0] = yx[0] = y[0] = hs[0] - 40;
256: pr[1] = yx[1] = y[1] = hs[1];
257:
258: y[2] = hs[2];
259:
260: if (hs[2] > 70) {
261: yx[2] = hs[2] - 30;
262: pr[2] = hs[2] - 15;
263: } else {
264: yx[2] = hs[2] + 30;
265: pr[2] = hs[2] + 15;
266: }
267: }
268: if (hs[0] >= 180 && hs[0] < 220) {
269: pr[0] = yx[0] = hs[0] - 170;
270: y[0] = hs[0] - 160;
271:
272: pr[1] = yx[1] = y[1] = hs[1];
273: y[2] = hs[2];
274:
275: if (hs[2] > 70) {
276: yx[2] = hs[2] - 30;
277: pr[2] = hs[2] - 15;
278: } else {
279: yx[2] = hs[2] + 30;
280: pr[2] = hs[2] + 15;
281: }
282: }
283: if (hs[0] >= 220 && hs[0] < 300) {
284: pr[0] = yx[0] = y[0] = hs[0];
285: pr[1] = yx[1] = y[1] = minMax(hs[1] - 60, 0, 100);
286: y[2] = hs[2];
287:
288: if (hs[2] > 70) {
289: yx[2] = hs[2] - 30;
290: pr[2] = hs[2] - 15;
291: } else {
292: yx[2] = hs[2] + 30;
293: pr[2] = hs[2] + 15;
294: }
295: }
296: if (hs[0] >= 300) {
297: if (hs[1] > 50) {
298: pr[1] = yx[1] = y[1] = hs[1] - 40;
299: } else {
300: pr[1] = yx[1] = y[1] = hs[1] + 40;
301: }
302:
303: pr[0] = yx[0] = y[0] = (hs[0] + 20) % 360;
304: y[2] = hs[2];
305:
306: if (hs[2] > 70) {
307: yx[2] = hs[2] - 30;
308: pr[2] = hs[2] - 15;
309: } else {
310: yx[2] = hs[2] + 30;
311: pr[2] = hs[2] + 15;
312: }
313: }
314:
315: result[3] = HSVtoRGB(y);
316: result[4] = HSVtoRGB(pr);
317: result[5] = HSVtoRGB(yx);
318:
319: // now change y again
320: y[0] = y[1] = 0;
321: y[2] = 100 - hs[2];
322: result[6] = HSVtoRGB(y);
323: y[2] = hs[2];
324: result[7] = HSVtoRGB(y);
325:
326: // now change pr again
327: pr[0] = pr[1] = 0;
328: pr[2] = hs[2] >= 50 ? 0 : 100;
329: result[8] = HSVtoRGB(pr);
330:
331: return result;
332: }
333:
334: private static double minMax(double x, double min, double max) {
335: if (x > max)
336: return max;
337: if (x < min)
338: return min;
339: return x;
340: }
341:
342: /**
343: * <p>Returns the color object represented by the HSV.</p>
344: * <p>The code is taken from Twyst <http://www.colormixers.com/>.<br />
345: * I've just translated it into Java.</p>
346: *
347: * @author Twyst, Patrick Gotthardt
348: * @param data An double[] with three items (0=h; s=1; 2=v)
349: * @return The Color object based on the HSV values
350: */
351: public static Color HSVtoRGB(double[] data) {
352: if (data == null || data.length != 3) {
353: throw new IllegalArgumentException(
354: "data must be an array of 3 items and must not be null!");
355: }
356: return HSVtoRGB(data[0], data[1], data[2]);
357: }
358:
359: /**
360: * <p>Returns the color object represented by the HSV.</p>
361: * <p>The code is taken from Twyst <http://www.colormixers.com/>.<br />
362: * I've just translated it into Java.</p>
363: * <p>All values must be between 0 and 255!.</p>
364: *
365: * @author Twyst, Patrick Gotthardt
366: * @param h The "H"-value of the color.
367: * @param s The "S"-value of the color.
368: * @param v The "V"-value of the color.
369: * @return The Color object based on the HSV values
370: */
371: public static Color HSVtoRGB(double h, double s, double v) {
372: int r = 0, g = 0, b = 0;
373:
374: if (s == 0) {
375: r = g = b = (int) Math.round(v * 2.55);
376: } else {
377: h = h / 60;
378: s = s / 100;
379: v = v / 100;
380:
381: double i = Math.floor(h);
382: double f = h - i;
383:
384: int p = (int) Math.round(255 * (v * (1 - s)));
385: int q = (int) Math.round(255 * (v * (1 - s * f)));
386: int t = (int) Math.round(255 * (v * (1 - s * (1 - f))));
387: int v2 = (int) Math.round(255 * v);
388:
389: switch ((int) i) {
390: case 0:
391: r = v2;
392: g = t;
393: b = p;
394: break;
395: case 1:
396: r = q;
397: g = v2;
398: b = p;
399: break;
400: case 2:
401: r = p;
402: g = v2;
403: b = t;
404: break;
405: case 3:
406: r = p;
407: g = q;
408: b = v2;
409: break;
410: case 4:
411: r = t;
412: g = p;
413: b = v2;
414: break;
415: default:
416: r = v2;
417: g = p;
418: b = q;
419: break;
420: }
421: }
422:
423: return new Color(r, g, b);
424: }
425:
426: /**
427: * <p>Returns the HSV representation of the RGB-Color. All values are between 0 and 255.</p>
428: * <p>The code is taken from Twyst <http://www.colormixers.com/>.<br />
429: * I've just translated it into Java.</p>
430: *
431: * @author Twyst, Patrick Gotthardt
432: * @param c The color to be translated to HSV.
433: * @return An double[] with three items (0=h; s=1; 2=v)
434: */
435: public static double[] RGBtoHSV(Color c) {
436: double[] hsv = new double[3];
437: int r = c.getRed(), g = c.getGreen(), b = c.getBlue();
438: int min = Math.min(Math.min(r, g), b); // get the smallest of all
439: int max = Math.max(Math.max(r, g), b); // get the biggest of all
440: int delta = max - min;
441:
442: double h = 0, s;
443: double v = 100 * max / 255;
444: // Is it a gray color?
445: if (delta == 0) {
446: h = s = 0;
447: } else {
448: s = (100 * delta) / max;
449:
450: double del_r = (100 * (((max - r) / 6) + (max / 2)))
451: / delta;
452: double del_g = (100 * (((max - g) / 6) + (max / 2)))
453: / delta;
454: double del_b = (100 * (((max - b) / 6) + (max / 2)))
455: / delta;
456:
457: if (r == max) {
458: h = 60 * (g - b) / delta;
459: } else if (g == max) {
460: h = 120 + 60 * (b - r) / delta;
461: } else if (b == max) {
462: h = 240 + 60 * (r - g) / delta;
463: }
464: if (h < 0) {
465: h = h + 360;
466: }
467: }
468: hsv[0] = h;
469: hsv[1] = s;
470: hsv[2] = v;
471:
472: return hsv;
473: }
474: }
|