PageRenderTime 55ms CodeModel.GetById 11ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 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}