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