View Javadoc
1   package com.github.celldynamics.quimp;
2   
3   import org.scijava.vecmath.Color3f;
4   import org.slf4j.Logger;
5   import org.slf4j.LoggerFactory;
6   
7   /**
8    * Just a class for colors, that does not use stupid floats represented as RGB in the range 0->1.
9    *
10   * @author tyson
11   */
12  public class QColor {
13  
14    /**
15     * The colour maps.
16     */
17    public static final String[] colourMaps = { "Summer", "Cool", "Hot", "Grey" };
18  
19    /**
20     * Color component.
21     */
22    public double red;
23    /**
24     * Color component.
25     */
26    public double green;
27    /**
28     * Color component.
29     */
30    public double blue;
31  
32    /**
33     * The Constant LOGGER.
34     */
35    static final Logger LOGGER = LoggerFactory.getLogger(QColor.class.getName());
36  
37    /**
38     * Copy constructor.
39     * 
40     * @param src object to copy
41     */
42    public QColorcs/quimp/QColor.html#QColor">QColor(final QColor src) {
43      red = src.red;
44      green = src.green;
45      blue = src.blue;
46    }
47  
48    /**
49     * Instantiates a new q color.
50     *
51     * @param r the r
52     * @param g the g
53     * @param b the b
54     */
55    public QColor(double r, double g, double b) {
56      this.setRGB(r, g, b);
57    }
58  
59    /**
60     * Prints the.
61     */
62    public void print() {
63      System.out.println("R:" + red + " G: " + green + " B: " + blue);
64    }
65  
66    /*
67     * (non-Javadoc)
68     * 
69     * @see java.lang.Object#hashCode()
70     */
71    @Override
72    public int hashCode() {
73      final int prime = 31;
74      int result = 1;
75      long temp;
76      temp = Double.doubleToLongBits(blue);
77      result = prime * result + (int) (temp ^ (temp >>> 32));
78      temp = Double.doubleToLongBits(green);
79      result = prime * result + (int) (temp ^ (temp >>> 32));
80      temp = Double.doubleToLongBits(red);
81      result = prime * result + (int) (temp ^ (temp >>> 32));
82      return result;
83    }
84  
85    /*
86     * (non-Javadoc)
87     * 
88     * @see java.lang.Object#equals(java.lang.Object)
89     */
90    @Override
91    public boolean equals(Object obj) {
92      if (this == obj) {
93        return true;
94      }
95      if (obj == null) {
96        return false;
97      }
98      if (!(obj instanceof QColor)) {
99        return false;
100     }
101     QColor"../../../../com/github/celldynamics/quimp/QColor.html#QColor">QColor other = (QColor) obj;
102     if (Double.doubleToLongBits(blue) != Double.doubleToLongBits(other.blue)) {
103       return false;
104     }
105     if (Double.doubleToLongBits(green) != Double.doubleToLongBits(other.green)) {
106       return false;
107     }
108     if (Double.doubleToLongBits(red) != Double.doubleToLongBits(other.red)) {
109       return false;
110     }
111     return true;
112   }
113 
114   /*
115    * (non-Javadoc)
116    * 
117    * @see java.lang.Object#toString()
118    */
119   @Override
120   public String toString() {
121     return "QColor [red=" + red + ", green=" + green + ", blue=" + blue + "]";
122   }
123 
124   /**
125    * Sets the RGB.
126    *
127    * @param r the r
128    * @param g the g
129    * @param b the b
130    */
131   public void setRGB(double r, double g, double b) {
132     red = r;
133     blue = b;
134     green = g;
135 
136     if (red > 1 || red < 0 || green > 1 || green < 0 || blue > 1 || blue < 0) {
137       System.out.println("32-Warning! Colour out of range:");
138       this.print();
139       red = 0;
140       blue = 0;
141       green = 0;
142       System.out.flush();
143       Exception e = new Exception();
144       e.printStackTrace();
145     }
146 
147   }
148 
149   /**
150    * Convert color to SVG codes.
151    * 
152    * @return SVG color representation
153    */
154   public String getColorSVG() {
155 
156     return "rgb(" + (red * 100) + "%," + (green * 100) + "%," + (blue * 100) + "%)";
157   }
158 
159   /**
160    * Gets the red.
161    *
162    * @return the red
163    */
164   public double getRed() {
165     return red;
166   }
167 
168   /**
169    * Gets the red.
170    *
171    * @param bits the bits
172    * @return the red - returns the color with a color space of size 'bits'
173    */
174   public int getRed(int bits) {
175     return (int) Math.round(red * bits);
176   }
177 
178   /**
179    * Gets the green.
180    *
181    * @return the green
182    */
183   public double getGreen() {
184     return green;
185   }
186 
187   /**
188    * Gets the green.
189    *
190    * @param bits the bits
191    * @return the green - returns the color with a color space of size 'bits'
192    */
193   public int getGreen(int bits) {
194     return (int) Math.round(green * bits);
195   }
196 
197   /**
198    * Gets the blue.
199    *
200    * @return the blue
201    */
202   public double getBlue() {
203     return blue;
204   }
205 
206   /**
207    * Gets the blue.
208    *
209    * @param bits the bits
210    * @return the blue - returns the color with a color space of size 'bits'
211    */
212   public int getBlue(int bits) {
213     return (int) Math.round(blue * bits);
214   }
215 
216   /**
217    * Gets the color int.
218    *
219    * @return the color int
220    */
221   public int getColorInt() {
222     return getRed(255) * 65536 + getGreen(255) * 256 + getBlue(255);
223   }
224 
225   /**
226    * Color int 23 f.
227    *
228    * @param c the c
229    * @return the color 3 f
230    */
231   public static Color3f colorInt23f(int c) {
232     float blueF = c % 256;
233     int s = (int) (c / 256);
234     float greenF = s % 256;
235     s = (int) (c / 256) / 256;
236     float redF = s % 256;
237 
238     redF = redF / 255;
239     greenF = greenF / 255;
240     blueF = blueF / 255;
241 
242     return new Color3f(redF, greenF, blueF);
243   }
244 
245   /**
246    * Gets the color BW.
247    *
248    * @param bits the bits
249    * @return the color BW
250    */
251   public int getColorBW(int bits) {
252     return (int) Math.round(((red + green + blue) / 3) * bits);
253   }
254 
255   /**
256    * ER color map 2.
257    *
258    * @param c the c
259    * @param d the d
260    * @param min the min
261    * @param max the max
262    * @return the q color
263    */
264   public static QColor erColorMap2(String c, double d, double min, double max) {
265     if (c.equals("rwb")) {
266       return rwbMap(d, max, min);
267     } else if (c.equals("rbb")) {
268       return rbbMap(d, max, min);
269     } else {
270       return rwbMap(d, max, min);
271     }
272   }
273 
274   /**
275    * RWB map.
276    *
277    * @param d the value
278    * @param max the max
279    * @param min the min
280    * @return the q color for d
281    */
282   public static QColor rwbMap(double d, double max, double min) {
283     double r = 1;
284     double g = 1;
285     double b = 1;
286 
287     if (min == 0 || max == 0) {
288       LOGGER.error("Min or max value is 0, returnig default color");
289       return new QColor(r, g, b);
290     }
291 
292     if (d == 0) {
293       return new QColor(1.0, 1.0, 1.0);
294     } else if (d > 0) { // red
295       r = 1;
296 
297       double p = (1 / max) * d;
298       if (p > 0.5) {
299         g = (1 - p) * 2;
300         b = 0;
301       } else {
302         g = 1;
303         b = (0.5 - p) * 2;
304       }
305 
306       return new QColor(r, g, b);
307     } else { // blu
308       b = 1;
309 
310       double p = (1 / min) * d;
311 
312       if (p > 0.5) {
313         g = (1 - p) * 2;
314         r = 0;
315       } else {
316         g = 1;
317         r = (0.5 - p) * 2;
318       }
319 
320       return new QColor(r, g, b);
321     }
322 
323   }
324 
325   private static QColor rbbMap(double d, double max, double min) {
326     double r = 0;
327     double g = 0;
328     double b = 0;
329 
330     if (d > max || d < min) {
331       System.out.println("Qcolor 141: d(" + d + ") not in min(" + min + ") or max(" + max + ")");
332       System.out.flush();
333       Exception e = new Exception();
334       e.printStackTrace();
335     }
336 
337     if (d == 0) { // black
338       return new QColor(0.0, 0.0, 0.0);
339     } else if (d > 0) { // red
340       double p = (1 / max) * d;
341 
342       if (p >= 0.5) {
343         g = (p - 0.5) * 2;
344         r = 1;
345       } else {
346         g = 0;
347         r = p * 2;
348       }
349 
350       return new QColor(r, g, b);
351     } else { // blu
352 
353       double p = (1 / min) * d;
354 
355       if (p >= 0.5) {
356         g = (p - 0.5) * 2;
357         b = 1;
358       } else {
359         g = 0;
360         b = p * 2;
361       }
362       return new QColor(r, g, b);
363     }
364 
365   }
366 
367   /**
368    * RB blut.
369    *
370    * @param reds the reds
371    * @param greens the greens
372    * @param blues the blues
373    * @return the int
374    */
375   static int RBBlut(byte[] reds, byte[] greens, byte[] blues) {
376     int[] r = { 0, 0, 1, 25, 49, 73, 98, 122, 146, 162, 173, 184, 195, 207, 217, 229, 240, 252, 255,
377         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
378     int[] g = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 35, 57, 79, 101, 117, 133, 147, 161, 175,
379         190, 205, 219, 234, 248, 255, 255, 255, 255 };
380     int[] b = { 0, 61, 96, 130, 165, 192, 220, 227, 210, 181, 151, 122, 93, 64, 35, 5, 0, 0, 0, 0,
381         0, 0, 0, 0, 0, 0, 0, 35, 98, 160, 223, 255 };
382     for (int i = 0; i < r.length; i++) {
383       reds[i] = (byte) r[i];
384       greens[i] = (byte) g[i];
385       blues[i] = (byte) b[i];
386     }
387     return r.length;
388   }
389 
390   /**
391    * Bw scale.
392    *
393    * @param value the value
394    * @param bits the bits
395    * @param max the max
396    * @param min the min
397    * @return the int
398    */
399   public static int bwScale(double value, int bits, double max, double min) {
400     if (value > max || value < min) {
401       // System.out.println("Warning! bwScale value not in range:
402       // "+value+" (min:"+ min +", max:" + max+")");
403       Exception e = new Exception();
404       e.printStackTrace();
405       System.exit(1);
406       return 0;
407     }
408 
409     return (int) Math.round((value - min) * ((bits - 1) / (max - min)));
410     // if(value==255)System.out.println("value: " + value+", min:" + min +
411     // ", max:" + max+", bits:" + bits+",temp: "+temp+", answ: " + answ);
412 
413   }
414 
415   /**
416    * Create a color map.
417    * 
418    * @param c choice of color map: "Summer"
419    * @param size size of the color map
420    * @return QColor array of length 'size'
421    */
422   public static QColor[] colourMap(String c, int size) {
423     QColormp/QColor.html#QColor">QColor[] map = new QColor[size];
424     double r;
425     double b;
426     double g;
427 
428     // set default colour
429     if (c == null || c.isEmpty()) {
430       c = "Summer";
431     }
432     if (c.equals("Summer")) {
433       r = 0.;
434       g = 0.5;
435       b = 0.4;
436       map[0] = new QColor(r, g, b);
437 
438       double dr = 1d / (double) size;
439       double dg = 0.5d / (double) size;
440 
441       for (int i = 1; i < size; i++) {
442         r += dr;
443         g += dg;
444         map[i] = new QColor(r, g, b);
445       }
446     } else if (c.equals("Cool")) {
447       r = 0.;
448       b = 0.5;
449       g = 0.4;
450       map[0] = new QColor(r, g, b);
451 
452       double dr = 1d / (double) size;
453       double db = 0.5d / (double) size;
454 
455       for (int i = 1; i < size; i++) {
456         r += dr;
457         b += db;
458         map[i] = new QColor(r, g, b);
459       }
460     } else if (c.equals("Hot")) {
461       // based on matlab code for Hot
462       r = 0.2d;
463       g = 0d;
464       b = 0;
465       map[0] = new QColor(r, g, b);
466 
467       double n = Math.floor(3d / 8d * size);
468 
469       for (int i = 0; i < size; i++) {
470 
471         r = (i + 1) / n;
472         if (r > 1) {
473           r = 1d;
474         }
475 
476         if (i < n) {
477           g = 0d;
478         } else {
479           g = (i - n + 1) / n;
480         }
481         if (g > 1) {
482           g = 1d;
483         }
484 
485         if (i < 2 * n) {
486           b = 0d;
487         } else {
488           b = (1 + i - 2 * n) / (size - (2 * n));
489         }
490         if (b > 1) {
491           b = 1d;
492         }
493         map[i] = new QColor(r, g, b);
494       }
495 
496     } else if (c.equals("Grey")) {
497       r = 0.1d;
498       g = 0.1d;
499       b = 0.1d;
500       map[0] = new QColor(r, g, b);
501 
502       double d = 0.9d / (double) size;
503 
504       for (int i = 1; i < size; i++) {
505         r += d;
506         g += d;
507         b += d;
508         map[i] = new QColor(r, g, b);
509       }
510 
511     } else {
512       for (int i = 0; i < size; i++) {
513         map[i] = new QColor(0.5, 0.5, 0.5);
514       }
515       System.out.println("warning: unknown color map: " + c);
516     }
517 
518     return map;
519   }
520 
521   /**
522    * Get a random light color.
523    * 
524    * @return random color
525    */
526   public static QColor lightColor() {
527     double r = (Math.random() / 1.3) + 0.23;
528     double g = (Math.random() / 1.3) + 0.23;
529     double b = (Math.random() / 1.3) + 0.23;
530 
531     return new QColor(r, g, b);
532   }
533 
534 }