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 17package android.graphics; 18 19import android.util.MathUtils; 20 21import java.util.HashMap; 22import 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 */ 35public 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 365 private static native void nativeRGBToHSV(int red, int greed, int blue, 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