• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import android.util.MathUtils;
20 
21 import java.util.HashMap;
22 import java.util.Locale;
23 
24 /**
25  * The Color class defines methods for creating and converting color ints.
26  * Colors are represented as packed ints, made up of 4 bytes: alpha, red,
27  * green, blue. The values are unpremultiplied, meaning any transparency is
28  * stored solely in the alpha component, and not in the color components. The
29  * components are stored as follows (alpha << 24) | (red << 16) |
30  * (green << 8) | blue. Each component ranges between 0..255 with 0
31  * meaning no contribution for that component, and 255 meaning 100%
32  * contribution. Thus opaque-black would be 0xFF000000 (100% opaque but
33  * no contributes from red, gree, blue, and opaque-white would be 0xFFFFFFFF
34  */
35 public class Color {
36     public static final int BLACK       = 0xFF000000;
37     public static final int DKGRAY      = 0xFF444444;
38     public static final int GRAY        = 0xFF888888;
39     public static final int LTGRAY      = 0xFFCCCCCC;
40     public static final int WHITE       = 0xFFFFFFFF;
41     public static final int RED         = 0xFFFF0000;
42     public static final int GREEN       = 0xFF00FF00;
43     public static final int BLUE        = 0xFF0000FF;
44     public static final int YELLOW      = 0xFFFFFF00;
45     public static final int CYAN        = 0xFF00FFFF;
46     public static final int MAGENTA     = 0xFFFF00FF;
47     public static final int TRANSPARENT = 0;
48 
49     /**
50      * Return the alpha component of a color int. This is the same as saying
51      * color >>> 24
52      */
alpha(int color)53     public static int alpha(int color) {
54         return color >>> 24;
55     }
56 
57     /**
58      * Return the red component of a color int. This is the same as saying
59      * (color >> 16) & 0xFF
60      */
red(int color)61     public static int red(int color) {
62         return (color >> 16) & 0xFF;
63     }
64 
65     /**
66      * Return the green component of a color int. This is the same as saying
67      * (color >> 8) & 0xFF
68      */
green(int color)69     public static int green(int color) {
70         return (color >> 8) & 0xFF;
71     }
72 
73     /**
74      * Return the blue component of a color int. This is the same as saying
75      * color & 0xFF
76      */
blue(int color)77     public static int blue(int color) {
78         return color & 0xFF;
79     }
80 
81     /**
82      * Return a color-int from red, green, blue components.
83      * The alpha component is implicity 255 (fully opaque).
84      * These component values should be [0..255], but there is no
85      * range check performed, so if they are out of range, the
86      * returned color is undefined.
87      * @param red  Red component [0..255] of the color
88      * @param green Green component [0..255] of the color
89      * @param blue  Blue component [0..255] of the color
90      */
rgb(int red, int green, int blue)91     public static int rgb(int red, int green, int blue) {
92         return (0xFF << 24) | (red << 16) | (green << 8) | blue;
93     }
94 
95     /**
96      * Return a color-int from alpha, red, green, blue components.
97      * These component values should be [0..255], but there is no
98      * range check performed, so if they are out of range, the
99      * returned color is undefined.
100      * @param alpha Alpha component [0..255] of the color
101      * @param red   Red component [0..255] of the color
102      * @param green Green component [0..255] of the color
103      * @param blue  Blue component [0..255] of the color
104      */
argb(int alpha, int red, int green, int blue)105     public static int argb(int alpha, int red, int green, int blue) {
106         return (alpha << 24) | (red << 16) | (green << 8) | blue;
107     }
108 
109     /**
110      * Returns the hue component of a color int.
111      *
112      * @return A value between 0.0f and 1.0f
113      *
114      * @hide Pending API council
115      */
hue(int color)116     public static float hue(int color) {
117         int r = (color >> 16) & 0xFF;
118         int g = (color >> 8) & 0xFF;
119         int b = color & 0xFF;
120 
121         int V = Math.max(b, Math.max(r, g));
122         int temp = Math.min(b, Math.min(r, g));
123 
124         float H;
125 
126         if (V == temp) {
127             H = 0;
128         } else {
129             final float vtemp = (float) (V - temp);
130             final float cr = (V - r) / vtemp;
131             final float cg = (V - g) / vtemp;
132             final float cb = (V - b) / vtemp;
133 
134             if (r == V) {
135                 H = cb - cg;
136             } else if (g == V) {
137                 H = 2 + cr - cb;
138             } else {
139                 H = 4 + cg - cr;
140             }
141 
142             H /= 6.f;
143             if (H < 0) {
144                 H++;
145             }
146         }
147 
148         return H;
149     }
150 
151     /**
152      * Returns the saturation component of a color int.
153      *
154      * @return A value between 0.0f and 1.0f
155      *
156      * @hide Pending API council
157      */
saturation(int color)158     public static float saturation(int color) {
159         int r = (color >> 16) & 0xFF;
160         int g = (color >> 8) & 0xFF;
161         int b = color & 0xFF;
162 
163 
164         int V = Math.max(b, Math.max(r, g));
165         int temp = Math.min(b, Math.min(r, g));
166 
167         float S;
168 
169         if (V == temp) {
170             S = 0;
171         } else {
172             S = (V - temp) / (float) V;
173         }
174 
175         return S;
176     }
177 
178     /**
179      * Returns the brightness component of a color int.
180      *
181      * @return A value between 0.0f and 1.0f
182      *
183      * @hide Pending API council
184      */
brightness(int color)185     public static float brightness(int color) {
186         int r = (color >> 16) & 0xFF;
187         int g = (color >> 8) & 0xFF;
188         int b = color & 0xFF;
189 
190         int V = Math.max(b, Math.max(r, g));
191 
192         return (V / 255.f);
193     }
194 
195     /**
196      * Parse the color string, and return the corresponding color-int.
197      * If the string cannot be parsed, throws an IllegalArgumentException
198      * exception. Supported formats are:
199      * #RRGGBB
200      * #AARRGGBB
201      * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta',
202      * 'yellow', 'lightgray', 'darkgray'
203      */
parseColor(String colorString)204     public static int parseColor(String colorString) {
205         if (colorString.charAt(0) == '#') {
206             // Use a long to avoid rollovers on #ffXXXXXX
207             long color = Long.parseLong(colorString.substring(1), 16);
208             if (colorString.length() == 7) {
209                 // Set the alpha value
210                 color |= 0x00000000ff000000;
211             } else if (colorString.length() != 9) {
212                 throw new IllegalArgumentException("Unknown color");
213             }
214             return (int)color;
215         } else {
216             Integer color = sColorNameMap.get(colorString.toLowerCase(Locale.US));
217             if (color != null) {
218                 return color;
219             }
220         }
221         throw new IllegalArgumentException("Unknown color");
222     }
223 
224     /**
225      * Convert HSB components to an ARGB color. Alpha set to 0xFF.
226      *     hsv[0] is Hue [0 .. 1)
227      *     hsv[1] is Saturation [0...1]
228      *     hsv[2] is Value [0...1]
229      * If hsv values are out of range, they are pinned.
230      * @param hsb  3 element array which holds the input HSB components.
231      * @return the resulting argb color
232      *
233      * @hide Pending API council
234      */
HSBtoColor(float[] hsb)235     public static int HSBtoColor(float[] hsb) {
236         return HSBtoColor(hsb[0], hsb[1], hsb[2]);
237     }
238 
239     /**
240      * Convert HSB components to an ARGB color. Alpha set to 0xFF.
241      *     hsv[0] is Hue [0 .. 1)
242      *     hsv[1] is Saturation [0...1]
243      *     hsv[2] is Value [0...1]
244      * If hsv values are out of range, they are pinned.
245      * @param h Hue component
246      * @param s Saturation component
247      * @param b Brightness component
248      * @return the resulting argb color
249      *
250      * @hide Pending API council
251      */
HSBtoColor(float h, float s, float b)252     public static int HSBtoColor(float h, float s, float b) {
253         h = MathUtils.constrain(h, 0.0f, 1.0f);
254         s = MathUtils.constrain(s, 0.0f, 1.0f);
255         b = MathUtils.constrain(b, 0.0f, 1.0f);
256 
257         float red = 0.0f;
258         float green = 0.0f;
259         float blue = 0.0f;
260 
261         final float hf = (h - (int) h) * 6.0f;
262         final int ihf = (int) hf;
263         final float f = hf - ihf;
264         final float pv = b * (1.0f - s);
265         final float qv = b * (1.0f - s * f);
266         final float tv = b * (1.0f - s * (1.0f - f));
267 
268         switch (ihf) {
269             case 0:         // Red is the dominant color
270                 red = b;
271                 green = tv;
272                 blue = pv;
273                 break;
274             case 1:         // Green is the dominant color
275                 red = qv;
276                 green = b;
277                 blue = pv;
278                 break;
279             case 2:
280                 red = pv;
281                 green = b;
282                 blue = tv;
283                 break;
284             case 3:         // Blue is the dominant color
285                 red = pv;
286                 green = qv;
287                 blue = b;
288                 break;
289             case 4:
290                 red = tv;
291                 green = pv;
292                 blue = b;
293                 break;
294             case 5:         // Red is the dominant color
295                 red = b;
296                 green = pv;
297                 blue = qv;
298                 break;
299         }
300 
301         return 0xFF000000 | (((int) (red * 255.0f)) << 16) |
302                 (((int) (green * 255.0f)) << 8) | ((int) (blue * 255.0f));
303     }
304 
305     /**
306      * Convert RGB components to HSV.
307      *     hsv[0] is Hue [0 .. 360)
308      *     hsv[1] is Saturation [0...1]
309      *     hsv[2] is Value [0...1]
310      * @param red  red component value [0..255]
311      * @param green  green component value [0..255]
312      * @param blue  blue component value [0..255]
313      * @param hsv  3 element array which holds the resulting HSV components.
314      */
RGBToHSV(int red, int green, int blue, float hsv[])315     public static void RGBToHSV(int red, int green, int blue, float hsv[]) {
316         if (hsv.length < 3) {
317             throw new RuntimeException("3 components required for hsv");
318         }
319         nativeRGBToHSV(red, green, blue, hsv);
320     }
321 
322     /**
323      * Convert the argb color to its HSV components.
324      *     hsv[0] is Hue [0 .. 360)
325      *     hsv[1] is Saturation [0...1]
326      *     hsv[2] is Value [0...1]
327      * @param color the argb color to convert. The alpha component is ignored.
328      * @param hsv  3 element array which holds the resulting HSV components.
329      */
colorToHSV(int color, float hsv[])330     public static void colorToHSV(int color, float hsv[]) {
331         RGBToHSV((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, hsv);
332     }
333 
334     /**
335      * Convert HSV components to an ARGB color. Alpha set to 0xFF.
336      *     hsv[0] is Hue [0 .. 360)
337      *     hsv[1] is Saturation [0...1]
338      *     hsv[2] is Value [0...1]
339      * If hsv values are out of range, they are pinned.
340      * @param hsv  3 element array which holds the input HSV components.
341      * @return the resulting argb color
342     */
HSVToColor(float hsv[])343     public static int HSVToColor(float hsv[]) {
344         return HSVToColor(0xFF, hsv);
345     }
346 
347     /**
348      * Convert HSV components to an ARGB color. The alpha component is passed
349      * through unchanged.
350      *     hsv[0] is Hue [0 .. 360)
351      *     hsv[1] is Saturation [0...1]
352      *     hsv[2] is Value [0...1]
353      * If hsv values are out of range, they are pinned.
354      * @param alpha the alpha component of the returned argb color.
355      * @param hsv  3 element array which holds the input HSV components.
356      * @return the resulting argb color
357     */
HSVToColor(int alpha, float hsv[])358     public static int HSVToColor(int alpha, float hsv[]) {
359         if (hsv.length < 3) {
360             throw new RuntimeException("3 components required for hsv");
361         }
362         return nativeHSVToColor(alpha, hsv);
363     }
364 
nativeRGBToHSV(int red, int greed, int blue, float hsv[])365     private static native void nativeRGBToHSV(int red, int greed, int blue, float hsv[]);
nativeHSVToColor(int alpha, float hsv[])366     private static native int nativeHSVToColor(int alpha, float hsv[]);
367 
368     private static final HashMap<String, Integer> sColorNameMap;
369 
370     static {
371         sColorNameMap = new HashMap<String, Integer>();
372         sColorNameMap.put("black", BLACK);
373         sColorNameMap.put("darkgray", DKGRAY);
374         sColorNameMap.put("gray", GRAY);
375         sColorNameMap.put("lightgray", LTGRAY);
376         sColorNameMap.put("white", WHITE);
377         sColorNameMap.put("red", RED);
378         sColorNameMap.put("green", GREEN);
379         sColorNameMap.put("blue", BLUE);
380         sColorNameMap.put("yellow", YELLOW);
381         sColorNameMap.put("cyan", CYAN);
382         sColorNameMap.put("magenta", MAGENTA);
383     }
384 }
385 
386