J'ai besoin de déterminer si une UIColor sélectionnée (choisie par l'utilisateur) est foncée ou lumineuse, donc je peux changer la couleur d'une ligne de texte qui se trouve au-dessus de cette couleur, pour une meilleure lisibilité.
Voici un exemple dans Flash/Actionscript (avec démo): http://web.archive.org/web/20100102024448/http://theflashblog.com/?p=17
Des pensées?
À la vôtre, André
[~ # ~] mise à jour [~ # ~]
Merci aux suggestions de tous, voici le code de travail:
- (void) updateColor:(UIColor *) newColor
{
const CGFloat *componentColors = CGColorGetComponents(newColor.CGColor);
CGFloat colorBrightness = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000;
if (colorBrightness < 0.5)
{
NSLog(@"my color is dark");
}
else
{
NSLog(@"my color is light");
}
}
Encore merci :)
Le W3C a les éléments suivants: http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
Si vous ne faites que du texte en noir ou blanc, utilisez le calcul de la luminosité des couleurs ci-dessus. S'il est inférieur à 125, utilisez du texte blanc. S'il est égal ou supérieur à 125, utilisez du texte noir.
modifier 1: biais vers le texte noir. :)
modifier 2: La formule à utiliser est ((valeur rouge * 299) + (valeur verte * 587) + (valeur bleue * 114))/1000.
Cette extension fonctionne avec des couleurs en niveaux de gris. Cependant, si vous créez toutes vos couleurs avec l'initialiseur RVB et n'utilisez pas les couleurs intégrées telles que UIColor.black
et UIColor.white
, alors vous pouvez éventuellement supprimer les vérifications supplémentaires.
extension UIColor {
// Check if the color is light or dark, as defined by the injected lightness threshold.
// Some people report that 0.7 is best. I suggest to find out for yourself.
// A nil value is returned if the lightness couldn't be determined.
func isLight(threshold: Float = 0.5) -> Bool? {
let originalCGColor = self.cgColor
// Now we need to convert it to the RGB colorspace. UIColor.white / UIColor.black are greyscale and not RGB.
// If you don't do this then you will crash when accessing components index 2 below when evaluating greyscale colors.
let RGBCGColor = originalCGColor.converted(to: CGColorSpaceCreateDeviceRGB(), intent: .defaultIntent, options: nil)
guard let components = RGBCGColor?.components else {
return nil
}
guard components.count >= 3 else {
return nil
}
let brightness = Float(((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000)
return (brightness > threshold)
}
}
Tests:
func testItWorks() {
XCTAssertTrue(UIColor.yellow.isLight()!, "Yellow is LIGHT")
XCTAssertFalse(UIColor.black.isLight()!, "Black is DARK")
XCTAssertTrue(UIColor.white.isLight()!, "White is LIGHT")
XCTAssertFalse(UIColor.red.isLight()!, "Red is DARK")
}
Remarque: mise à jour vers Swift 3 12/7/18
En utilisant la réponse d'Erik Nedwidek, j'ai trouvé ce petit extrait de code pour une inclusion facile.
- (UIColor *)readableForegroundColorForBackgroundColor:(UIColor*)backgroundColor {
size_t count = CGColorGetNumberOfComponents(backgroundColor.CGColor);
const CGFloat *componentColors = CGColorGetComponents(backgroundColor.CGColor);
CGFloat darknessScore = 0;
if (count == 2) {
darknessScore = (((componentColors[0]*255) * 299) + ((componentColors[0]*255) * 587) + ((componentColors[0]*255) * 114)) / 1000;
} else if (count == 4) {
darknessScore = (((componentColors[0]*255) * 299) + ((componentColors[1]*255) * 587) + ((componentColors[2]*255) * 114)) / 1000;
}
if (darknessScore >= 125) {
return [UIColor blackColor];
}
return [UIColor whiteColor];
}
extension UIColor {
var isLight: Bool {
var white: CGFloat = 0
getWhite(&white, alpha: nil)
return white > 0.5
}
}
// Usage
if color.isLight {
label.textColor = UIColor.black
} else {
label.textColor = UIColor.white
}
Ma solution à ce problème dans une catégorie (tirée d'autres réponses ici). Fonctionne également avec des couleurs en niveaux de gris, ce qui, au moment de la rédaction, ne fait aucune des autres réponses.
@interface UIColor (Ext)
- (BOOL) colorIsLight;
@end
@implementation UIColor (Ext)
- (BOOL) colorIsLight {
CGFloat colorBrightness = 0;
CGColorSpaceRef colorSpace = CGColorGetColorSpace(self.CGColor);
CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
if(colorSpaceModel == kCGColorSpaceModelRGB){
const CGFloat *componentColors = CGColorGetComponents(self.CGColor);
colorBrightness = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000;
} else {
[self getWhite:&colorBrightness alpha:0];
}
return (colorBrightness >= .5f);
}
@end
Version Swift 4
extension UIColor {
func isLight() -> Bool {
guard let components = cgColor.components, components.count > 2 else {return false}
let brightness = ((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000
return (brightness > 0.5)
}
}
Plus simple Swift 3 extension:
extension UIColor {
func isLight() -> Bool {
guard let components = cgColor.components else { return false }
let redBrightness = components[0] * 299
let greenBrightness = components[1] * 587
let blueBrightness = components[2] * 114
let brightness = (redBrightness + greenBrightness + blueBrightness) / 1000
return brightness > 0.5
}
}
Si vous préférez la version bloc:
BOOL (^isDark)(UIColor *) = ^(UIColor *color){
const CGFloat *component = CGColorGetComponents(color.CGColor);
CGFloat brightness = ((component[0] * 299) + (component[1] * 587) + (component[2] * 114)) / 1000;
if (brightness < 0.75)
return YES;
return NO;
};
UIColor a la méthode suivante pour convertir en espace colorimétrique HSB:
- (BOOL)getHue:(CGFloat *)hue saturation:(CGFloat *)saturation brightness:(CGFloat *)brightness alpha:(CGFloat *)alpha;
La méthode suivante consiste à trouver la couleur claire ou foncée en Swift langue basée sur le blanc en couleur.
func isLightColor(color: UIColor) -> Bool
{
var white: CGFloat = 0.0
color.getWhite(&white, alpha: nil)
var isLight = false
if white >= 0.5
{
isLight = true
NSLog("color is light: %f", white)
}
else
{
NSLog("Color is dark: %f", white)
}
return isLight
}
La méthode suivante consiste à trouver la couleur claire ou foncée dans Swift en utilisant des composants de couleur.
func isLightColor(color: UIColor) -> Bool
{
var isLight = false
var componentColors = CGColorGetComponents(color.CGColor)
var colorBrightness: CGFloat = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000;
if (colorBrightness >= 0.5)
{
isLight = true
NSLog("my color is light")
}
else
{
NSLog("my color is dark")
}
return isLight
}
Pour moi, utiliser uniquement CGColorGetComponents n'a pas fonctionné, j'obtiens 2 composants pour UIColors comme le blanc. Je dois donc d'abord vérifier l'espace colorimétrique. C'est ce que j'ai trouvé qui a fini par être la version Swift de la réponse de @ mattsven.
Espace colorimétrique pris à partir d'ici: https://stackoverflow.com/a/16981916/4905076
extension UIColor {
func isLight() -> Bool {
if let colorSpace = self.cgColor.colorSpace {
if colorSpace.model == .rgb {
guard let components = cgColor.components, components.count > 2 else {return false}
let brightness = ((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000
return (brightness > 0.5)
}
else {
var white : CGFloat = 0.0
self.getWhite(&white, alpha: nil)
return white >= 0.5
}
}
return false
}
Pour tout ce qui n'est pas grisâtre, l'inverse RVB d'une couleur est généralement très contrasté avec elle. La démo inverse simplement la couleur et la désature (la convertit en gris).
Mais générer une belle combinaison de couleurs apaisantes est assez compliqué. Regarder :
http://particletree.com/notebook/calculating-color-contrast-for-legible-text/
- (BOOL)isColorLight:(UIColor*)color
{
CGFloat white = 0;
[color getWhite:&white alpha:nil];
return (white >= .5);
}
L'utilisation de HandyUIKit en fait une évidence , par exemple:
import HandyUIKit
UIColor.black.hlca.luminance // => 0.0
UIColor.white.hlca.luminance // => 1.0
UIColor.lightGray.hlca.luminance // => 0.70
UIColor.darkGray.hlca.luminance // => 0.36
UIColor.red.hlca.luminance // => 0.53
UIColor.green.hlca.luminance // => 0.87
UIColor.blue.hlca.luminance // => 0.32
En utilisant simplement .hlca.luminance
sur n'importe quelle instance de UIColor
vous donnera la valeur correcte pour la légèreté perçue . La plupart des autres approches ne prennent pas en compte le fait que les humains perçoivent des couleurs différentes (même lorsque la saturation et la luminosité sont les mêmes) à différents niveaux de luminosité . Les valeurs luminance
en tiennent compte.
Lisez cet excellent article de blog ou l'entrée Wikipedia sur le LAB espace colorimétrique pour plus d'explications. Ils expliqueront également pourquoi le système de couleurs HSB avec sa valeur brightness
n'est que la moitié de la solution.
À titre indicatif: notez que la valeur luminance
de la couleur vert pur est beaucoup plus élevée que sur la couleur bleu pur . C'est tout simplement parce que les humains perçoivent le bleu pur comme une couleur beaucoup plus sombre que le vert pur.
Si vous souhaitez retrouver la luminosité de la couleur, voici un pseudo code:
public float GetBrightness(int red, int blue, int green)
{
float num = red / 255f;
float num2 = blue / 255f;
float num3 = green / 255f;
float num4 = num;
float num5 = num;
if (num2 > num4)
num4 = num2;
if (num3 > num4)
num4 = num3;
if (num2 < num5)
num5 = num2;
if (num3 < num5)
num5 = num3;
return ((num4 + num5) / 2f);
}
S'il est> 0,5, il est clair et sinon sombre.