Utiliser la couleur et color.darker dans Android?

Bon, j’ai une variable entière dans mon application. C’est la valeur d’une couleur, définie par un sélecteur de couleur dans mes préférences. Maintenant, je dois utiliser à la fois cette couleur et une version plus sombre de n’importe quelle couleur.

Maintenant, je sais qu’en Java standard, il existe une méthode Color.darker (), mais il ne semble pas y avoir d’équivalent dans Android. Est-ce que quelqu’un connaît un équivalent ou des solutions de contournement?

Le plus simple, je pense, serait de convertir en HSV, de faire le noircissement et de reconvertir:

float[] hsv = new float[3]; int color = getColor(); Color.colorToHSV(color, hsv); hsv[2] *= 0.8f; // value component color = Color.HSVToColor(hsv); 

Pour éclaircir, une approche simple peut consister à multiplier le composant valeur par quelque chose> 1.0. Cependant, vous devrez fixer le résultat à la plage [0.0, 1.0]. En outre, la simple multiplication ne va pas alléger le noir.

Par conséquent, une meilleure solution est la suivante: réduire la différence par rapport à la version 1.0 du composant valeur pour alléger:

 hsv[2] = 1.0f - 0.8f * (1.0f - hsv[2]); 

Ceci est tout à fait parallèle à l’approche de l’assombrissement, en utilisant simplement 1 comme origine au lieu de 0. Cela fonctionne pour éclairer n’importe quelle couleur (même le noir) et n’a besoin d’aucun serrage. Il pourrait être simplifié pour:

 hsv[2] = 0.2f + 0.8f * hsv[2]; 

Cependant, en raison des effets d’arrondi possibles de l’arithmétique en virgule flottante, je crains que le résultat ne dépasse 1,0f (peut-être un bit). Mieux vaut s’en tenir à la formule un peu plus compliquée.

Voici ce que j’ai créé:

 /** * Returns darker version of specified color. */ public static int darker (int color, float factor) { int a = Color.alpha( color ); int r = Color.red( color ); int g = Color.green( color ); int b = Color.blue( color ); return Color.argb( a, Math.max( (int)(r * factor), 0 ), Math.max( (int)(g * factor), 0 ), Math.max( (int)(b * factor), 0 ) ); } 

La réponse de Ted pour éclaircir une couleur ne fonctionnait pas pour moi, alors voici une solution qui pourrait aider quelqu’un d’autre:

 /** * Lightens a color by a given factor. * * @param color * The color to lighten * @param factor * The factor to lighten the color. 0 will make the color unchanged. 1 will make the * color white. * @return lighter version of the specified color. */ public static int lighter(int color, float factor) { int red = (int) ((Color.red(color) * (1 - factor) / 255 + factor) * 255); int green = (int) ((Color.green(color) * (1 - factor) / 255 + factor) * 255); int blue = (int) ((Color.blue(color) * (1 - factor) / 255 + factor) * 255); return Color.argb(Color.alpha(color), red, green, blue); } 

La routine Java Color pour assombrir et éclaircir ne nécessite rien de spécial. En fait, c’est simplement la compréhension déroulée de la luminosité appliquée aux couleurs pertinentes. C’est-à-dire que vous pouvez simplement prendre les valeurs rouges, vertes et bleues. Multipliez-les par n’importe quel facteur, assurez-vous qu’ils tombent correctement dans la gamme.

Voici le code trouvé dans la classe Color.

 private static final double FACTOR = 0.7; //... public Color darker() { return new Color(Math.max((int)(getRed() *FACTOR), 0), Math.max((int)(getGreen()*FACTOR), 0), Math.max((int)(getBlue() *FACTOR), 0), getAlpha()); } 

De toute évidence, à partir de cela, nous pouvons voir comment faire ce processus dans Android. Prenez les valeurs RVB, multipliez-les par un facteur et serrez-les dans la gamme. (Recodé à partir de zéro pour des raisons de licence).

 public int crimp(int c) { return Math.min(Math.max(c, 0), 255); } public int darken(int color) { double factor = 0.7; return (color & 0xFF000000) | (crimp((int) (((color >> 16) & 0xFF) * factor)) << 16) | (crimp((int) (((color >> 8) & 0xFF) * factor)) << 8) | (crimp((int) (((color) & 0xFF) * factor))); } 

Notez que ceci est la même chose que l'augmentation de la luminosité dans HSB, le B est simplement le facteur le plus lumineux, la teinte est le rapport entre les différentes couleurs et S est la distance entre elles. Donc, si nous prenons simplement toutes les couleurs et les multiplions par un facteur, nous nous retrouvons avec les mêmes couleurs dans le même mélange avec un peu plus de blanc / noir.

Un grand nombre d’espaces colorimésortingques modernes effectuent également cette opération en calculant la valeur Y à travers les différentes composantes de couleur qui représentent le mieux la luminosité. Ainsi, si vous vouliez convertir en une meilleure forme de Y ou de L à travers l'un des espaces de couleurs modernes et les déconvertir, les autres espaces de couleurs ont une meilleure forme de gamma en termes de consortingbution de chaque couleur à la luminosité, la légèreté, la valeur la blancheur, la noirceur, ou quoi que l’appelle cet espace colorimésortingque. Cela ferait un meilleur travail, mais dans la plupart des cas, cela est solide.

Donc, à l'extrême, vous pouvez le faire en convertissant en Lab, en diminuant le composant L et en le reconvertissant.

Voici le code pour faire cela:

 static int darken(int color) { double factor = 0.7; double[] returnarray = new double[3]; convertRGBsRGB(returnarray, ((color >> 16) & 0xFF), ((color >> 8) & 0xFF), (color & 0xFF)); convertRGBXYZ(returnarray,returnarray[0], returnarray[1], returnarray[2]); convertXYZLab(returnarray,returnarray[0], returnarray[1], returnarray[2]); returnarray[0] *= factor; convertLabXYZ(returnarray,returnarray[0], returnarray[1], returnarray[2]); convertXYZRGB(returnarray,returnarray[0], returnarray[1], returnarray[2]); return (color & 0xFF000000) | convertsRGBRGB(returnarray); } static void convertRGBsRGB(double[] returnarray, int R, int G, int B) { double var_R = (((double) R) / 255.0d); //RGB from 0 to 255 double var_G = (((double) G) / 255.0d); double var_B = (((double) B) / 255.0d); returnarray[0] = var_R; returnarray[1] = var_G; returnarray[2] = var_B; } static int convertsRGBRGB(double[] sRGB) { int red = (int) (sRGB[0] * 255); int green = (int) (sRGB[1] * 255); int blue = (int) (sRGB[2] * 255); red = crimp(red); green = crimp(green); blue = crimp(blue); return (red << 16) | (green << 8) | blue; } public static int crimp(int v) { if (v > 0xff) { v = 0xff; } if (v < 0) { v = 0; } return v; } public static final double ref_X = 95.047; //ref_X = 95.047 Observer= 2°, Illuminant= D65 public static final double ref_Y = 100.000; //ref_Y = 100.000 public static final double ref_Z = 108.883;//ref_Z = 108.883 static void convertRGBXYZ(double[] returnarray, double var_R, double var_G, double var_B) { if (var_R > 0.04045) { var_R = Math.pow(((var_R + 0.055) / 1.055), 2.4); } else { var_R = var_R / 12.92; } if (var_G > 0.04045) { var_G = Math.pow(((var_G + 0.055) / 1.055), 2.4); } else { var_G = var_G / 12.92; } if (var_B > 0.04045) { var_B = Math.pow(((var_B + 0.055) / 1.055), 2.4); } else { var_B = var_B / 12.92; } var_R = var_R * 100; var_G = var_G * 100; var_B = var_B * 100; //Observer. = 2°, Illuminant = D65 double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805; double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722; double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505; returnarray[0] = X; returnarray[1] = Y; returnarray[2] = Z; } static void convertXYZLab(double[] returnarray, double X, double Y, double Z) { double var_X = X / ref_X; double var_Y = Y / ref_Y; double var_Z = Z / ref_Z; if (var_X > 0.008856) { var_X = Math.cbrt(var_X); } else { var_X = (7.787 * var_X) + (16.0d / 116.0d); } if (var_Y > 0.008856) { var_Y = Math.cbrt(var_Y); } else { var_Y = (7.787 * var_Y) + (16.0d / 116.0d); } if (var_Z > 0.008856) { var_Z = Math.cbrt(var_Z); } else { var_Z = (7.787 * var_Z) + (16.0d / 116.0d); } double CIE_L = (116 * var_Y) - 16; double CIE_a = 500 * (var_X - var_Y); double CIE_b = 200 * (var_Y - var_Z); returnarray[0] = CIE_L; returnarray[1] = CIE_a; returnarray[2] = CIE_b; } static void convertLabXYZ(double[] returnarray, double CIE_L, double CIE_a, double CIE_b) { double var_Y = (CIE_L + 16) / 116; double var_X = CIE_a / 500 + var_Y; double var_Z = var_Y - CIE_b / 200; if ((var_Y * var_Y * var_Y) > 0.008856) { var_Y = (var_Y * var_Y * var_Y); } else { var_Y = (((var_Y - 16) / 116)) / 7.787; } if ((var_X * var_X * var_X) > 0.008856) { var_X = (var_X * var_X * var_X); } else { var_X = ((var_X - 16) / 116) / 7.787; } if ((var_Z * var_Z * var_Z) > 0.008856) { var_Z = (var_Z * var_Z * var_Z); } else { var_Z = ((var_Z - 16) / 116) / 7.787; } double X = ref_X * var_X; //ref_X = 95.047 Observer= 2°, Illuminant= D65 double Y = ref_Y * var_Y; //ref_Y = 100.000 double Z = ref_Z * var_Z; //ref_Z = 108.883 returnarray[0] = X; returnarray[1] = Y; returnarray[2] = Z; } static void convertXYZRGB(double[] returnarray, double X, double Y, double Z) { double var_X = X / 100; //X from 0 to 95.047 (Observer = 2°, Illuminant = D65) double var_Y = Y / 100; //Y from 0 to 100.000 double var_Z = Z / 100; //Z from 0 to 108.883 double var_R = (var_X * 3.2406) + (var_Y * -1.5372) + (var_Z * -0.4986); double var_G = (var_X * -0.9689) + (var_Y * 1.8758) + (var_Z * 0.0415); double var_B = (var_X * 0.0557) + (var_Y * -0.2040) + (var_Z * 1.0570); if (var_R > 0.0031308) { var_R = 1.055 * (Math.pow(var_R, (1f / 2.4f))) - 0.055; } else { var_R = 12.92 * var_R; } if (var_G > 0.0031308) { var_G = 1.055 * (Math.pow(var_G, (1f / 2.4f))) - 0.055; } else { var_G = 12.92 * var_G; } if (var_B > 0.0031308) { var_B = 1.055 * (Math.pow(var_B, (1f / 2.4f))) - 0.055; } else { var_B = 12.92 * var_B; } returnarray[0] = var_R; returnarray[1] = var_G; returnarray[2] = var_B; } 

Mes quelques lignes font la même chose que Color.darken (), voici une image d'un jeu de couleurs échantillon (ces couleurs sont la distance maximale de toutes les couleurs précédentes via CIE-LabD2000, et les utilisent simplement comme un ensemble d'échantillons de couleurs robustes).

Couleur d'index, Color.darker () et mon darken () de base, le tout à un facteur de 0,7. indice vs plus sombre vs plus sombre (ceux-ci devraient être identiques)

Suivant pour ceux qui ont suggéré d'utiliser Lab pour assombrir,

Index Color, Color.darker () et Lab Darker (), tous à un facteur de 0,7. entrer la description de l'image ici (est-ce une amélioration qui vaut le coup de temps?)