/alaspatial/src/main/java/org/ala/spatial/analysis/heatmap/ColorUtilities.java
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 35package org.ala.spatial.analysis.heatmap; 36 37/** 38 * Updated from 39 * https://swingx.dev.java.net/source/browse/swingx/trunk/src/java/org/jdesktop/swingx/graphics/ColorUtilities.java?rev=1496 40 * 41 * @author ajay 42 */ 43 44import java.awt.Color; 45 46/** 47 * <p><code>ColorUtilities</code> contains a set of tools to perform 48 * common color operations easily.</p> 49 * 50 * @author Romain Guy <romain.guy@mac.com> 51 */ 52public class ColorUtilities { 53 private ColorUtilities() { 54 } 55 56 /** 57 * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given 58 * RGB color. All three HSL components are between 0.0 and 1.0.</p> 59 * 60 * @param color the RGB color to convert 61 * @return a new array of 3 floats corresponding to the HSL components 62 */ 63 public static float[] RGBtoHSL(Color color) { 64 return RGBtoHSL(color.getRed(), color.getGreen(), color.getBlue(), null); 65 } 66 67 /** 68 * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given 69 * RGB color. All three HSL components are between 0.0 and 1.0.</p> 70 * 71 * @param color the RGB color to convert 72 * @param hsl a pre-allocated array of floats; can be null 73 * @return <code>hsl</code> if non-null, a new array of 3 floats otherwise 74 * @throws IllegalArgumentException if <code>hsl</code> has a length lower 75 * than 3 76 */ 77 public static float[] RGBtoHSL(Color color, float[] hsl) { 78 return RGBtoHSL(color.getRed(), color.getGreen(), color.getBlue(), hsl); 79 } 80 81 /** 82 * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given 83 * RGB color. All three HSL components are between 0.0 and 1.0.</p> 84 * 85 * @param r the red component, between 0 and 255 86 * @param g the green component, between 0 and 255 87 * @param b the blue component, between 0 and 255 88 * @return a new array of 3 floats corresponding to the HSL components 89 */ 90 public static float[] RGBtoHSL(int r, int g, int b) { 91 return RGBtoHSL(r, g, b, null); 92 } 93 94 /** 95 * <p>Returns the HSL (Hue/Saturation/Luminance) equivalent of a given 96 * RGB color. All three HSL components are floats between 0.0 and 1.0.</p> 97 * 98 * @param r the red component, between 0 and 255 99 * @param g the green component, between 0 and 255 100 * @param b the blue component, between 0 and 255 101 * @param hsl a pre-allocated array of floats; can be null 102 * @return <code>hsl</code> if non-null, a new array of 3 floats otherwise 103 * @throws IllegalArgumentException if <code>hsl</code> has a length lower 104 * than 3 105 */ 106 public static float[] RGBtoHSL(int r, int g, int b, float[] hsl) { 107 if (hsl == null) { 108 hsl = new float[3]; 109 } else if (hsl.length < 3) { 110 throw new IllegalArgumentException("hsl array must have a length of" + 111 " at least 3"); 112 } 113 114 if (r < 0) r = 0; 115 else if (r > 255) r = 255; 116 if (g < 0) g = 0; 117 else if (g > 255) g = 255; 118 if (b < 0) b = 0; 119 else if (b > 255) b = 255; 120 121 float var_R = (r / 255f); 122 float var_G = (g / 255f); 123 float var_B = (b / 255f); 124 125 float var_Min; 126 float var_Max; 127 float del_Max; 128 129 if (var_R > var_G) { 130 var_Min = var_G; 131 var_Max = var_R; 132 } else { 133 var_Min = var_R; 134 var_Max = var_G; 135 } 136 if (var_B > var_Max) { 137 var_Max = var_B; 138 } 139 if (var_B < var_Min) { 140 var_Min = var_B; 141 } 142 143 del_Max = var_Max - var_Min; 144 145 float H, S, L; 146 L = (var_Max + var_Min) / 2f; 147 148 if (del_Max - 0.01f <= 0.0f) { 149 H = 0; 150 S = 0; 151 } else { 152 if (L < 0.5f) { 153 S = del_Max / (var_Max + var_Min); 154 } else { 155 S = del_Max / (2 - var_Max - var_Min); 156 } 157 158 float del_R = (((var_Max - var_R) / 6f) + (del_Max / 2f)) / del_Max; 159 float del_G = (((var_Max - var_G) / 6f) + (del_Max / 2f)) / del_Max; 160 float del_B = (((var_Max - var_B) / 6f) + (del_Max / 2f)) / del_Max; 161 162 if (var_R == var_Max) { 163 H = del_B - del_G; 164 } else if (var_G == var_Max) { 165 H = (1 / 3f) + del_R - del_B; 166 } else { 167 H = (2 / 3f) + del_G - del_R; 168 } 169 if (H < 0) { 170 H += 1; 171 } 172 if (H > 1) { 173 H -= 1; 174 } 175 } 176 177 hsl[0] = H; 178 hsl[1] = S; 179 hsl[2] = L; 180 181 return hsl; 182 } 183 184 /** 185 * <p>Returns the RGB equivalent of a given HSL (Hue/Saturation/Luminance) 186 * color.</p> 187 * 188 * @param h the hue component, between 0.0 and 1.0 189 * @param s the saturation component, between 0.0 and 1.0 190 * @param l the luminance component, between 0.0 and 1.0 191 * @return a new <code>Color</code> object equivalent to the HSL components 192 */ 193 public static Color HSLtoRGB(float h, float s, float l) { 194 int[] rgb = HSLtoRGB(h, s, l, null); 195 return new Color(rgb[0], rgb[1], rgb[2]); 196 } 197 198 /** 199 * <p>Returns the RGB equivalent of a given HSL (Hue/Saturation/Luminance) 200 * color. All three RGB components are integers between 0 and 255.</p> 201 * 202 * @param h the hue component, between 0.0 and 1.0 203 * @param s the saturation component, between 0.0 and 1.0 204 * @param l the luminance component, between 0.0 and 1.0 205 * @param rgb a pre-allocated array of ints; can be null 206 * @return <code>rgb</code> if non-null, a new array of 3 ints otherwise 207 * @throws IllegalArgumentException if <code>rgb</code> has a length lower 208 * than 3 209 */ 210 public static int[] HSLtoRGB(float h, float s, float l, int[] rgb) { 211 if (rgb == null) { 212 rgb = new int[3]; 213 } else if (rgb.length < 3) { 214 throw new IllegalArgumentException("rgb array must have a length of" + 215 " at least 3"); 216 } 217 218 if (h < 0) h = 0.0f; 219 else if (h > 1.0f) h = 1.0f; 220 if (s < 0) s = 0.0f; 221 else if (s > 1.0f) s = 1.0f; 222 if (l < 0) l = 0.0f; 223 else if (l > 1.0f) l = 1.0f; 224 225 int R, G, B; 226 227 if (s - 0.01f <= 0.0f) { 228 R = (int) (l * 255.0f); 229 G = (int) (l * 255.0f); 230 B = (int) (l * 255.0f); 231 } else { 232 float var_1, var_2; 233 if (l < 0.5f) { 234 var_2 = l * (1 + s); 235 } else { 236 var_2 = (l + s) - (s * l); 237 } 238 var_1 = 2 * l - var_2; 239 240 R = (int) (255.0f * hue2RGB(var_1, var_2, h + (1.0f / 3.0f))); 241 G = (int) (255.0f * hue2RGB(var_1, var_2, h)); 242 B = (int) (255.0f * hue2RGB(var_1, var_2, h - (1.0f / 3.0f))); 243 } 244 245 rgb[0] = R; 246 rgb[1] = G; 247 rgb[2] = B; 248 249 return rgb; 250 } 251 252 private static float hue2RGB(float v1, float v2, float vH) { 253 if (vH < 0.0f) { 254 vH += 1.0f; 255 } 256 if (vH > 1.0f) { 257 vH -= 1.0f; 258 } 259 if ((6.0f * vH) < 1.0f) { 260 return (v1 + (v2 - v1) * 6.0f * vH); 261 } 262 if ((2.0f * vH) < 1.0f) { 263 return (v2); 264 } 265 if ((3.0f * vH) < 2.0f) { 266 return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f); 267 } 268 return (v1); 269 } 270}