1528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell/* 2528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * Copyright (C) 2014 The Android Open Source Project 3528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * 4528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * Licensed under the Apache License, Version 2.0 (the "License"); 5528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * you may not use this file except in compliance with the License. 6528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * You may obtain a copy of the License at 7528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * 8528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * http://www.apache.org/licenses/LICENSE-2.0 9528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * 10528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * Unless required by applicable law or agreed to in writing, software 11528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * distributed under the License is distributed on an "AS IS" BASIS, 12528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * See the License for the specific language governing permissions and 14528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell * limitations under the License. 15528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell */ 16528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 17528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwellpackage com.android.contacts.common.util; 18528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 19d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwellimport com.android.contacts.common.R; 20d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell 21d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwellimport android.content.res.Resources; 22d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwellimport android.content.res.TypedArray; 23528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwellimport android.os.Trace; 24528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 25528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwellpublic class MaterialColorMapUtils { 26528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 27d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell private final TypedArray sPrimaryColors; 28d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell private final TypedArray sSecondaryColors; 29528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 30d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell public MaterialColorMapUtils(Resources resources) { 31d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell sPrimaryColors = resources.obtainTypedArray( 32d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell com.android.contacts.common.R.array.letter_tile_colors); 33d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell sSecondaryColors = resources.obtainTypedArray( 34d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell com.android.contacts.common.R.array.letter_tile_colors_dark); 35d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell } 36528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 37528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell public static class MaterialPalette { 38528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell public MaterialPalette(int primaryColor, int secondaryColor) { 39528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell mPrimaryColor = primaryColor; 40528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell mSecondaryColor = secondaryColor; 41528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell } 42528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell public final int mPrimaryColor; 43528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell public final int mSecondaryColor; 44528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell } 45528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 46528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell /** 47d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell * Return primary and secondary colors from the Material color palette that are similar to 48d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell * {@param color}. 49528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell */ 50d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell public MaterialPalette calculatePrimaryAndSecondaryColor(int color) { 51528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell Trace.beginSection("calculatePrimaryAndSecondaryColor"); 52528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 53d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee final float colorHue = hue(color); 54528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell float minimumDistance = Float.MAX_VALUE; 55528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell int indexBestMatch = 0; 56d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell for (int i = 0; i < sPrimaryColors.length(); i++) { 57d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell final int primaryColor = sPrimaryColors.getColor(i, 0); 58d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell final float comparedHue = hue(primaryColor); 59528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell // No need to be perceptually accurate when calculating color distances since 60528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell // we are only mapping to 15 colors. Being slightly inaccurate isn't going to change 61528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell // the mapping very often. 62528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell final float distance = Math.abs(comparedHue - colorHue); 63528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell if (distance < minimumDistance) { 64528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell minimumDistance = distance; 65528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell indexBestMatch = i; 66528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell } 67528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell } 68528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 69528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell Trace.endSection(); 70d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell return new MaterialPalette(sPrimaryColors.getColor(indexBestMatch, 0), 71d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell sSecondaryColors.getColor(indexBestMatch, 0)); 72528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell } 73528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 74d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell public static MaterialPalette getDefaultPrimaryAndSecondaryColors(Resources resources) { 75d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell final int primaryColor = resources.getColor( 76d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell R.color.quickcontact_default_photo_tint_color); 77d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell final int secondaryColor = resources.getColor( 78d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell R.color.quickcontact_default_photo_tint_color_dark); 79d4d290d39d14e17683ec86b07a150c9df35505aeBrian Attwell return new MaterialPalette(primaryColor, secondaryColor); 80528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell } 81528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell 82d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee /** 83d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee * Returns the hue component of a color int. 84d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee * 85d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee * @return A value between 0.0f and 1.0f 86d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee */ 87d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee public static float hue(int color) { 88d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee int r = (color >> 16) & 0xFF; 89d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee int g = (color >> 8) & 0xFF; 90d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee int b = color & 0xFF; 91d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee 92d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee int V = Math.max(b, Math.max(r, g)); 93d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee int temp = Math.min(b, Math.min(r, g)); 94d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee 95d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee float H; 96d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee 97d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee if (V == temp) { 98d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee H = 0; 99d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee } else { 100d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee final float vtemp = V - temp; 101d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee final float cr = (V - r) / vtemp; 102d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee final float cg = (V - g) / vtemp; 103d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee final float cb = (V - b) / vtemp; 104d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee 105d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee if (r == V) { 106d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee H = cb - cg; 107d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee } else if (g == V) { 108d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee H = 2 + cr - cb; 109d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee } else { 110d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee H = 4 + cg - cr; 111d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee } 112d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee 113d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee H /= 6.f; 114d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee if (H < 0) { 115d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee H++; 116d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee } 117d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee } 118d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee 119d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee return H; 120d585ac1c9ea385751b69897a9efb907655296f66Yorke Lee } 121528cb5eae10cc221cdc989035b0dc5e21f09684bBrian Attwell} 122