KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > internal > text > revisions > Colors


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.internal.text.revisions;
12
13 import org.eclipse.core.runtime.Assert;
14
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.graphics.RGB;
17
18 /**
19  * Utility for color operations.
20  *
21  * @since 3.3
22  */

23 public final class Colors {
24     /*
25      * Implementation note: Color computation assumes sRGB, which is probably not true, and does not
26      * always give good results. CIE based algorithms would be better, see
27      * http://www.w3.org/TR/PNG-ColorAppendix.html and http://en.wikipedia.org/wiki/Lab_color_space
28      */

29
30     /**
31      * Returns the human-perceived brightness of a color as float in [0.0, 1.0]. The used RGB
32      * weights come from http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9.
33      *
34      * @param rgb the color
35      * @return the gray-scale value
36      */

37     public static float brightness(RGB rgb) {
38         return Math.min(1f, (0.2126f * rgb.red + 0.7152f * rgb.green + 0.0722f * rgb.blue + 0.5f) / 255f);
39     }
40
41     /**
42      * Normalizes a color in its perceived brightness. Yellows are darkened, while blues and reds
43      * are lightened. Depending on the hue, the brightness range within the RGB gamut may be
44      * different, outside values are clipped. Note that this is an approximation; the returned RGB
45      * is not guaranteed to have the requested {@link #brightness(RGB) brightness}.
46      *
47      * @param color the color to normalize
48      * @param brightness the requested brightness, in [0, 1]
49      * @return a normalized version of <code>color</code>
50      * @see #brightness(RGB)
51      */

52     public static RGB adjustBrightness(RGB color, float brightness) {
53         float[] hsi= toHSI(color);
54         float psychoFactor= brightness - brightness(color);
55         float weight= 0.5f; // found by trial and error
56
hsi[2]= Math.max(0, Math.min(1.0f, hsi[2] + psychoFactor * weight));
57         color= fromHSI(hsi);
58         return color;
59     }
60
61     /**
62      * Converts an {@link RGB} to an <a HREF="http://en.wikipedia.org/wiki/HSL_color_space">HSI</a>
63      * triplet.
64      *
65      * @param color the color to convert
66      * @return the HSI float array of length 3
67      */

68     private static float[] toHSI(RGB color) {
69         float r = color.red / 255f;
70         float g = color.green / 255f;
71         float b = color.blue / 255f;
72         float max = Math.max(Math.max(r, g), b);
73         float min = Math.min(Math.min(r, g), b);
74         float delta = max - min;
75         float maxPlusMin= max + min;
76         float intensity = maxPlusMin / 2;
77         float saturation= intensity < 0.5 ? delta / maxPlusMin : delta / (2 - maxPlusMin);
78
79         float hue = 0;
80         if (delta != 0) {
81             if (r == max) {
82                 hue = (g - b) / delta;
83             } else {
84                 if (g == max) {
85                     hue = 2 + (b - r) / delta;
86                 } else {
87                     hue = 4 + (r - g) / delta;
88                 }
89             }
90             hue *= 60;
91             if (hue < 0) hue += 360;
92         }
93         return new float[] {hue, saturation, intensity};
94     }
95
96     /**
97      * Converts a <a HREF="http://en.wikipedia.org/wiki/HSL_color_space">HSI</a> triplet to an RGB.
98      *
99      * @param hsi the HSI values
100      * @return the RGB corresponding to the HSI spec
101      */

102     private static RGB fromHSI(float[] hsi) {
103         float r, g, b;
104         float hue= hsi[0];
105         float saturation= hsi[1];
106         float intensity= hsi[2];
107         if (saturation == 0) {
108             r = g = b = intensity;
109         } else {
110             float temp2= intensity < 0.5f ? intensity * (1.0f + saturation) : (intensity + saturation) - (intensity * saturation);
111             float temp1= 2f * intensity - temp2;
112             if (hue == 360) hue = 0;
113             hue /= 360;
114
115             r= hue2RGB(temp1, temp2, hue + 1f/3f);
116             g= hue2RGB(temp1, temp2, hue);
117             b= hue2RGB(temp1, temp2, hue - 1f/3f);
118         }
119
120         int red = (int)(r * 255 + 0.5);
121         int green = (int)(g * 255 + 0.5);
122         int blue = (int)(b * 255 + 0.5);
123         return new RGB(red, green, blue);
124     }
125
126     private static float hue2RGB(float t1, float t2, float hue) {
127         if (hue < 0)
128             hue += 1;
129         else if (hue > 1)
130             hue -= 1;
131         if (6f * hue < 1)
132             return t1 +(t2 - t1) * 6f * hue;
133         if (2f * hue < 1)
134             return t2;
135         if (3f * hue < 2)
136             return t1 + (t2 - t1) * (2f/3f - hue) * 6f;
137         return t1;
138     }
139
140     /**
141      * Returns an RGB that lies between the given foreground and background
142      * colors using the given mixing factor. A <code>factor</code> of 1.0 will produce a
143      * color equal to <code>fg</code>, while a <code>factor</code> of 0.0 will produce one
144      * equal to <code>bg</code>.
145      * @param bg the background color
146      * @param fg the foreground color
147      * @param factor the mixing factor, must be in [0,&nbsp;1]
148      *
149      * @return the interpolated color
150      */

151     public static RGB blend(RGB bg, RGB fg, float factor) {
152         Assert.isLegal(bg != null);
153         Assert.isLegal(fg != null);
154         Assert.isLegal(factor >= 0f && factor <= 1f);
155
156         float complement= 1f - factor;
157         return new RGB(
158                 (int) (complement * bg.red + factor * fg.red),
159                 (int) (complement * bg.green + factor * fg.green),
160                 (int) (complement * bg.blue + factor * fg.blue)
161         );
162     }
163
164     /**
165      * Returns an array of colors in a smooth palette from <code>start</code> to <code>end</code>.
166      * <p>
167      * The returned array has size <code>steps</code>, and the color at index 0 is <code>start</code>, the color
168      * at index <code>steps&nbsp;-&nbsp;1</code> is <code>end</code>.
169      *
170      * @param start the start color of the palette
171      * @param end the end color of the palette
172      * @param steps the requested size, must be &gt; 0
173      * @return an array of <code>steps</code> colors in the palette from <code>start</code> to <code>end</code>
174      */

175     public static RGB[] palette(RGB start, RGB end, int steps) {
176         Assert.isLegal(start != null);
177         Assert.isLegal(end != null);
178         Assert.isLegal(steps > 0);
179         
180         if (steps == 1)
181             return new RGB[] { start };
182
183         float step= 1.0f / (steps - 1);
184         RGB[] gradient= new RGB[steps];
185         for (int i= 0; i < steps; i++)
186             gradient[i]= blend(start, end, step * i);
187
188         return gradient;
189     }
190
191     /**
192      * Returns an array of colors with hues evenly distributed on the hue wheel defined by the <a
193      * HREF="http://en.wikipedia.org/wiki/HSV_color_space">HSB color space</a>. The returned array
194      * has size <code>steps</code>. The distance <var>d</var> between two successive colors is
195      * in [120&#176;,&nbsp;180&#176;].
196      * <p>
197      * The color at a given <code>index</code> has the hue returned by
198      * {@linkplain #computeHue(int) computeHue(index)}; i.e. the computed hues are not equidistant,
199      * but adaptively distributed on the color wheel.
200      * </p>
201      * <p>
202      * The first six colors returned correspond to the following {@link SWT} color constants:
203      * {@link SWT#COLOR_RED red}, {@link SWT#COLOR_GREEN green}, {@link SWT#COLOR_BLUE blue},
204      * {@link SWT#COLOR_YELLOW yellow}, {@link SWT#COLOR_CYAN cyan},
205      * {@link SWT#COLOR_MAGENTA magenta}.
206      * </p>
207      *
208      * @param steps the requested size, must be &gt;= 2
209      * @return an array of <code>steps</code> colors evenly distributed on the color wheel
210      */

211     public static RGB[] rainbow(int steps) {
212         Assert.isLegal(steps >= 2);
213
214         RGB[] rainbow= new RGB[steps];
215         for (int i= 0; i < steps; i++)
216             rainbow[i]= new RGB(computeHue(i), 1f, 1f);
217
218         return rainbow;
219     }
220
221     /**
222      * Returns an indexed hue in [0&#176;,&nbsp;360&#176;), distributing the hues evenly on the hue wheel
223      * defined by the <a HREF="http://en.wikipedia.org/wiki/HSV_color_space">HSB (or HSV) color
224      * space</a>. The distance <var>d</var> between two successive colors is in [120&#176;,&nbsp;180&#176;].
225      * <p>
226      * The first six colors returned correspond to the following {@link SWT} color constants:
227      * {@link SWT#COLOR_RED red}, {@link SWT#COLOR_GREEN green}, {@link SWT#COLOR_BLUE blue},
228      * {@link SWT#COLOR_YELLOW yellow}, {@link SWT#COLOR_CYAN cyan},
229      * {@link SWT#COLOR_MAGENTA magenta}.
230      * </p>
231      *
232      * @param index the index of the color, must be &gt;= 0
233      * @return a color hue in [0&#176;,&nbsp;360&#176;)
234      * @see RGB#RGB(float, float, float)
235      */

236     public static float computeHue(final int index) {
237         Assert.isLegal(index >= 0);
238         /*
239          * Base 3 gives a nice partitioning for RGB colors with red, green, blue being the colors
240          * 0,1,2, and yellow, cyan, magenta colors 3,4,5.
241          */

242         final int base= 3;
243         final float range= 360f;
244
245         // partition the baseRange by using the least significant bit to select one half of the
246
// partitioning
247
int baseIndex= index / base;
248         float baseRange= range / base;
249         float baseOffset= 0f;
250         while (baseIndex > 0) {
251             baseRange /= 2;
252             int lsb= baseIndex % 2;
253             baseOffset += lsb * baseRange;
254             baseIndex >>= 1;
255         }
256
257         final int baseMod= index % base;
258         final float hue= baseOffset + baseMod * range / base;
259         Assert.isTrue(hue >= 0 && hue < 360);
260         return hue;
261     }
262
263     private Colors() {
264         // not instantiatable
265
}
266
267 }
268
Popular Tags