Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.util

File ColorUtils.java

 

Coverage histogram

../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

44
126
9
1
375
221
46
0.37
14
9
5.11

Classes

Class Line # Actions
ColorUtils 32 126 46 16
0.9106145591.1%
 

Contributing tests

This file is covered by 94 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    /**
22    * author: Lauren Michelle Lui
23    */
24   
25    package jalview.util;
26   
27    import java.awt.Color;
28    import java.util.HashMap;
29    import java.util.Map;
30    import java.util.Random;
31   
 
32    public class ColorUtils
33    {
34    private static final int MAX_CACHE_SIZE = 1729;
35    /*
36    * a cache for colours generated from text strings
37    */
38    static Map<String, Color> myColours = new HashMap<>();
39   
40    /**
41    * Generates a random color, will mix with input color. Code taken from
42    * http://stackoverflow
43    * .com/questions/43044/algorithm-to-randomly-generate-an-aesthetically
44    * -pleasing-color-palette
45    *
46    * @param mix
47    * @return Random color in RGB
48    */
 
49  3 toggle public static final Color generateRandomColor(Color mix)
50    {
51  3 Random random = new Random();
52  3 int red = random.nextInt(256);
53  3 int green = random.nextInt(256);
54  3 int blue = random.nextInt(256);
55   
56    // mix the color
57  3 if (mix != null)
58    {
59  3 red = (red + mix.getRed()) / 2;
60  3 green = (green + mix.getGreen()) / 2;
61  3 blue = (blue + mix.getBlue()) / 2;
62    }
63   
64  3 Color color = new Color(red, green, blue);
65  3 return color;
66   
67    }
68   
69    /**
70    * Convert to Tk colour code format
71    *
72    * @param colour
73    * @return
74    * @see http
75    * ://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/colortool.html#
76    * tkcode
77    */
 
78  13 toggle public static final String toTkCode(Color colour)
79    {
80  13 String colstring = "#" + ((colour.getRed() < 16) ? "0" : "")
81    + Integer.toHexString(colour.getRed())
82  13 + ((colour.getGreen() < 16) ? "0" : "")
83    + Integer.toHexString(colour.getGreen())
84  13 + ((colour.getBlue() < 16) ? "0" : "")
85    + Integer.toHexString(colour.getBlue());
86  13 return colstring;
87    }
88   
89    /**
90    * Returns a colour three shades darker. Note you can't guarantee that
91    * brighterThan reverses this, as darkerThan may result in black.
92    *
93    * @param col
94    * @return
95    */
 
96  4 toggle public static Color darkerThan(Color col)
97    {
98  4 return col == null ? null : col.darker().darker().darker();
99    }
100   
101    /**
102    * Returns a colour three shades brighter. Note you can't guarantee that
103    * darkerThan reverses this, as brighterThan may result in white.
104    *
105    * @param col
106    * @return
107    */
 
108  4 toggle public static Color brighterThan(Color col)
109    {
110  4 return col == null ? null : col.brighter().brighter().brighter();
111    }
112   
113    /**
114    * Returns a color between minColour and maxColour; the RGB values are in
115    * proportion to where 'value' lies between minValue and maxValue
116    *
117    * @param value
118    * @param minValue
119    * @param minColour
120    * @param maxValue
121    * @param maxColour
122    * @return
123    */
 
124  7 toggle public static Color getGraduatedColour(float value, float minValue,
125    Color minColour, float maxValue, Color maxColour)
126    {
127  7 if (minValue == maxValue)
128    {
129  1 return minColour;
130    }
131  6 if (value < minValue)
132    {
133  1 value = minValue;
134    }
135  6 if (value > maxValue)
136    {
137  1 value = maxValue;
138    }
139   
140    /*
141    * prop = proportion of the way value is from minValue to maxValue
142    */
143  6 float prop = (value - minValue) / (maxValue - minValue);
144  6 float r = minColour.getRed()
145    + prop * (maxColour.getRed() - minColour.getRed());
146  6 float g = minColour.getGreen()
147    + prop * (maxColour.getGreen() - minColour.getGreen());
148  6 float b = minColour.getBlue()
149    + prop * (maxColour.getBlue() - minColour.getBlue());
150  6 return new Color(r / 255, g / 255, b / 255);
151    }
152   
153    /**
154    * 'Fades' the given colour towards white by the specified proportion. A
155    * factor of 1 or more results in White, a factor of 0 leaves the colour
156    * unchanged, and a factor between 0 and 1 results in a proportionate change
157    * of RGB values towards (255, 255, 255).
158    * <p>
159    * A negative bleachFactor can be specified to darken the colour towards Black
160    * (0, 0, 0).
161    *
162    * @param colour
163    * @param bleachFactor
164    * @return
165    */
 
166  73785 toggle public static Color bleachColour(Color colour, float bleachFactor)
167    {
168  73785 if (bleachFactor >= 1f)
169    {
170  4141 return Color.WHITE;
171    }
172  69644 if (bleachFactor <= -1f)
173    {
174  2 return Color.BLACK;
175    }
176  69642 if (bleachFactor == 0f)
177    {
178  608 return colour;
179    }
180   
181  69034 int red = colour.getRed();
182  69034 int green = colour.getGreen();
183  69034 int blue = colour.getBlue();
184   
185  69034 if (bleachFactor > 0)
186    {
187  69032 red += (255 - red) * bleachFactor;
188  69032 green += (255 - green) * bleachFactor;
189  69032 blue += (255 - blue) * bleachFactor;
190  69032 return new Color(red, green, blue);
191    }
192    else
193    {
194  2 float factor = 1 + bleachFactor;
195  2 red *= factor;
196  2 green *= factor;
197  2 blue *= factor;
198  2 return new Color(red, green, blue);
199    }
200    }
201   
202    /**
203    * Parses a string into a Color, where the accepted formats are
204    * <ul>
205    * <li>an AWT colour name e.g. white</li>
206    * <li>a hex colour value (without prefix) e.g. ff0000</li>
207    * <li>an rgb triple e.g. 100,50,150</li>
208    * </ul>
209    *
210    * @param colour
211    * @return the parsed colour, or null if parsing fails
212    */
 
213  22358 toggle public static Color parseColourString(String colour)
214    {
215  22358 if (colour == null)
216    {
217  5 return null;
218    }
219  22353 colour = colour.trim();
220   
221  22353 Color col = null;
222  22353 try
223    {
224  22353 int value = Integer.parseInt(colour, 16);
225  22242 col = new Color(value);
226    } catch (NumberFormatException ex)
227    {
228    }
229   
230  22353 if (col == null)
231    {
232  111 col = ColorUtils.getAWTColorFromName(colour);
233    }
234   
235  22353 if (col == null)
236    {
237  42 try
238    {
239  42 String[] tokens = colour.split(",");
240  42 if (tokens.length == 3)
241    {
242  16 int r = Integer.parseInt(tokens[0].trim());
243  16 int g = Integer.parseInt(tokens[1].trim());
244  16 int b = Integer.parseInt(tokens[2].trim());
245  16 col = new Color(r, g, b);
246    }
247    } catch (Exception ex)
248    {
249    // non-numeric token or out of 0-255 range
250    }
251    }
252   
253  22353 return col;
254    }
255   
256    /**
257    * Constructs a colour from a text string. The hashcode of the whole string is
258    * scaled to the range 0-135. This is added to RGB values made from the
259    * hashcode of each third of the string, and scaled to the range 20-229.
260    *
261    * @param name
262    * @return
263    */
 
264  40 toggle public static Color createColourFromName(String name)
265    {
266  40 if (name == null)
267    {
268  1 return Color.white;
269    }
270  39 if (myColours.containsKey(name))
271    {
272  11 return myColours.get(name);
273    }
274  28 int lsize = name.length();
275  28 int start = 0;
276  28 int end = lsize / 3;
277   
278  28 int rgbOffset = Math.abs(name.hashCode() % 10) * 15; // 0-135
279   
280    /*
281    * red: first third
282    */
283  28 int r = Math.abs(name.substring(start, end).hashCode() + rgbOffset)
284    % 210 + 20;
285  28 start = end;
286  28 end += lsize / 3;
287  28 if (end > lsize)
288    {
289  0 end = lsize;
290    }
291   
292    /*
293    * green: second third
294    */
295  28 int g = Math.abs(name.substring(start, end).hashCode() + rgbOffset)
296    % 210 + 20;
297   
298    /*
299    * blue: third third
300    */
301  28 int b = Math.abs(name.substring(end).hashCode() + rgbOffset) % 210 + 20;
302   
303  28 Color color = new Color(r, g, b);
304   
305  28 if (myColours.size() < MAX_CACHE_SIZE)
306    {
307  28 myColours.put(name, color);
308    }
309   
310  28 return color;
311    }
312   
313    /**
314    * Returns the Color constant for a given colour name e.g. "pink", or null if
315    * the name is not recognised
316    *
317    * @param name
318    * @return
319    */
 
320  118 toggle public static Color getAWTColorFromName(String name)
321    {
322  118 if (name == null)
323    {
324  1 return null;
325    }
326  117 Color col = null;
327  117 name = name.toLowerCase();
328   
329    // or make a static map; or use reflection on the field name
330  117 switch (name)
331    {
332  6 case "black":
333  6 col = Color.black;
334  6 break;
335  28 case "blue":
336  28 col = Color.blue;
337  28 break;
338  0 case "cyan":
339  0 col = Color.cyan;
340  0 break;
341  0 case "darkgray":
342  0 col = Color.darkGray;
343  0 break;
344  0 case "gray":
345  0 col = Color.gray;
346  0 break;
347  7 case "green":
348  7 col = Color.green;
349  7 break;
350  1 case "lightgray":
351  1 col = Color.lightGray;
352  1 break;
353  0 case "magenta":
354  0 col = Color.magenta;
355  0 break;
356  1 case "orange":
357  1 col = Color.orange;
358  1 break;
359  2 case "pink":
360  2 col = Color.pink;
361  2 break;
362  22 case "red":
363  22 col = Color.red;
364  22 break;
365  5 case "white":
366  5 col = Color.white;
367  5 break;
368  1 case "yellow":
369  1 col = Color.yellow;
370  1 break;
371    }
372   
373  117 return col;
374    }
375    }