Subversion Repositories distributed

Rev

Rev 43 | Details | Compare with Previous | Last modification | View Log | RSS feed

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