/alaspatial/src/main/java/org/ala/spatial/analysis/heatmap/ColorUtilities.java

http://alageospatialportal.googlecode.com/ · Java · 270 lines · 138 code · 28 blank · 104 comment · 51 complexity · 5497eb6822104fa1fafcbad608431105 MD5 · raw file

  1. /*
  2. * $Id$
  3. *
  4. * Dual-licensed under LGPL (Sun and Romain Guy) and BSD (Romain Guy).
  5. *
  6. * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
  7. * Santa Clara, California 95054, U.S.A. All rights reserved.
  8. *
  9. * Copyright (c) 2006 Romain Guy <romain.guy@mac.com>
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * 3. The name of the author may not be used to endorse or promote products
  21. * derived from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  24. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  25. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  26. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  28. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  32. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. package org.ala.spatial.analysis.heatmap;
  35. /**
  36. * Updated from
  37. * https://swingx.dev.java.net/source/browse/swingx/trunk/src/java/org/jdesktop/swingx/graphics/ColorUtilities.java?rev=1496
  38. *
  39. * @author ajay
  40. */
  41. import java.awt.Color;
  42. /**
  43. * <p><code>ColorUtilities</code> contains a set of tools to perform
  44. * common color operations easily.</p>
  45. *
  46. * @author Romain Guy <romain.guy@mac.com>
  47. */
  48. public class ColorUtilities {
  49. private ColorUtilities() {
  50. }
  51. /**
  52. * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given
  53. * RGB color. All three HSL components are between 0.0 and 1.0.</p>
  54. *
  55. * @param color the RGB color to convert
  56. * @return a new array of 3 floats corresponding to the HSL components
  57. */
  58. public static float[] RGBtoHSL(Color color) {
  59. return RGBtoHSL(color.getRed(), color.getGreen(), color.getBlue(), null);
  60. }
  61. /**
  62. * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given
  63. * RGB color. All three HSL components are between 0.0 and 1.0.</p>
  64. *
  65. * @param color the RGB color to convert
  66. * @param hsl a pre-allocated array of floats; can be null
  67. * @return <code>hsl</code> if non-null, a new array of 3 floats otherwise
  68. * @throws IllegalArgumentException if <code>hsl</code> has a length lower
  69. * than 3
  70. */
  71. public static float[] RGBtoHSL(Color color, float[] hsl) {
  72. return RGBtoHSL(color.getRed(), color.getGreen(), color.getBlue(), hsl);
  73. }
  74. /**
  75. * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given
  76. * RGB color. All three HSL components are between 0.0 and 1.0.</p>
  77. *
  78. * @param r the red component, between 0 and 255
  79. * @param g the green component, between 0 and 255
  80. * @param b the blue component, between 0 and 255
  81. * @return a new array of 3 floats corresponding to the HSL components
  82. */
  83. public static float[] RGBtoHSL(int r, int g, int b) {
  84. return RGBtoHSL(r, g, b, null);
  85. }
  86. /**
  87. * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given
  88. * RGB color. All three HSL components are floats between 0.0 and 1.0.</p>
  89. *
  90. * @param r the red component, between 0 and 255
  91. * @param g the green component, between 0 and 255
  92. * @param b the blue component, between 0 and 255
  93. * @param hsl a pre-allocated array of floats; can be null
  94. * @return <code>hsl</code> if non-null, a new array of 3 floats otherwise
  95. * @throws IllegalArgumentException if <code>hsl</code> has a length lower
  96. * than 3
  97. */
  98. public static float[] RGBtoHSL(int r, int g, int b, float[] hsl) {
  99. if (hsl == null) {
  100. hsl = new float[3];
  101. } else if (hsl.length < 3) {
  102. throw new IllegalArgumentException("hsl array must have a length of" +
  103. " at least 3");
  104. }
  105. if (r < 0) r = 0;
  106. else if (r > 255) r = 255;
  107. if (g < 0) g = 0;
  108. else if (g > 255) g = 255;
  109. if (b < 0) b = 0;
  110. else if (b > 255) b = 255;
  111. float var_R = (r / 255f);
  112. float var_G = (g / 255f);
  113. float var_B = (b / 255f);
  114. float var_Min;
  115. float var_Max;
  116. float del_Max;
  117. if (var_R > var_G) {
  118. var_Min = var_G;
  119. var_Max = var_R;
  120. } else {
  121. var_Min = var_R;
  122. var_Max = var_G;
  123. }
  124. if (var_B > var_Max) {
  125. var_Max = var_B;
  126. }
  127. if (var_B < var_Min) {
  128. var_Min = var_B;
  129. }
  130. del_Max = var_Max - var_Min;
  131. float H, S, L;
  132. L = (var_Max + var_Min) / 2f;
  133. if (del_Max - 0.01f <= 0.0f) {
  134. H = 0;
  135. S = 0;
  136. } else {
  137. if (L < 0.5f) {
  138. S = del_Max / (var_Max + var_Min);
  139. } else {
  140. S = del_Max / (2 - var_Max - var_Min);
  141. }
  142. float del_R = (((var_Max - var_R) / 6f) + (del_Max / 2f)) / del_Max;
  143. float del_G = (((var_Max - var_G) / 6f) + (del_Max / 2f)) / del_Max;
  144. float del_B = (((var_Max - var_B) / 6f) + (del_Max / 2f)) / del_Max;
  145. if (var_R == var_Max) {
  146. H = del_B - del_G;
  147. } else if (var_G == var_Max) {
  148. H = (1 / 3f) + del_R - del_B;
  149. } else {
  150. H = (2 / 3f) + del_G - del_R;
  151. }
  152. if (H < 0) {
  153. H += 1;
  154. }
  155. if (H > 1) {
  156. H -= 1;
  157. }
  158. }
  159. hsl[0] = H;
  160. hsl[1] = S;
  161. hsl[2] = L;
  162. return hsl;
  163. }
  164. /**
  165. * <p>Returns the RGB equivalent of a given HSL (Hue/Saturation/Luminance)
  166. * color.</p>
  167. *
  168. * @param h the hue component, between 0.0 and 1.0
  169. * @param s the saturation component, between 0.0 and 1.0
  170. * @param l the luminance component, between 0.0 and 1.0
  171. * @return a new <code>Color</code> object equivalent to the HSL components
  172. */
  173. public static Color HSLtoRGB(float h, float s, float l) {
  174. int[] rgb = HSLtoRGB(h, s, l, null);
  175. return new Color(rgb[0], rgb[1], rgb[2]);
  176. }
  177. /**
  178. * <p>Returns the RGB equivalent of a given HSL (Hue/Saturation/Luminance)
  179. * color. All three RGB components are integers between 0 and 255.</p>
  180. *
  181. * @param h the hue component, between 0.0 and 1.0
  182. * @param s the saturation component, between 0.0 and 1.0
  183. * @param l the luminance component, between 0.0 and 1.0
  184. * @param rgb a pre-allocated array of ints; can be null
  185. * @return <code>rgb</code> if non-null, a new array of 3 ints otherwise
  186. * @throws IllegalArgumentException if <code>rgb</code> has a length lower
  187. * than 3
  188. */
  189. public static int[] HSLtoRGB(float h, float s, float l, int[] rgb) {
  190. if (rgb == null) {
  191. rgb = new int[3];
  192. } else if (rgb.length < 3) {
  193. throw new IllegalArgumentException("rgb array must have a length of" +
  194. " at least 3");
  195. }
  196. if (h < 0) h = 0.0f;
  197. else if (h > 1.0f) h = 1.0f;
  198. if (s < 0) s = 0.0f;
  199. else if (s > 1.0f) s = 1.0f;
  200. if (l < 0) l = 0.0f;
  201. else if (l > 1.0f) l = 1.0f;
  202. int R, G, B;
  203. if (s - 0.01f <= 0.0f) {
  204. R = (int) (l * 255.0f);
  205. G = (int) (l * 255.0f);
  206. B = (int) (l * 255.0f);
  207. } else {
  208. float var_1, var_2;
  209. if (l < 0.5f) {
  210. var_2 = l * (1 + s);
  211. } else {
  212. var_2 = (l + s) - (s * l);
  213. }
  214. var_1 = 2 * l - var_2;
  215. R = (int) (255.0f * hue2RGB(var_1, var_2, h + (1.0f / 3.0f)));
  216. G = (int) (255.0f * hue2RGB(var_1, var_2, h));
  217. B = (int) (255.0f * hue2RGB(var_1, var_2, h - (1.0f / 3.0f)));
  218. }
  219. rgb[0] = R;
  220. rgb[1] = G;
  221. rgb[2] = B;
  222. return rgb;
  223. }
  224. private static float hue2RGB(float v1, float v2, float vH) {
  225. if (vH < 0.0f) {
  226. vH += 1.0f;
  227. }
  228. if (vH > 1.0f) {
  229. vH -= 1.0f;
  230. }
  231. if ((6.0f * vH) < 1.0f) {
  232. return (v1 + (v2 - v1) * 6.0f * vH);
  233. }
  234. if ((2.0f * vH) < 1.0f) {
  235. return (v2);
  236. }
  237. if ((3.0f * vH) < 2.0f) {
  238. return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f);
  239. }
  240. return (v1);
  241. }
  242. }