Pregunta

I necesidad de determinar si una UIColor seleccionado (elegido por el usuario) es oscuro o brillante, por lo que puede cambiar el color de una línea de texto que se encuentra en la parte superior de ese color, para una mejor legibilidad.

Este es un ejemplo de Flash / Actionscript (con demostración): http://web.archive.org/web/ 20100102024448 / http:? p = 173 //theflashblog.com/

¿Alguna idea?

Cheers, Andre

Actualizar

Gracias a las sugerencias de todos, aquí está el código de trabajo:

- (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");
    }
}

Gracias una vez más:)

¿Fue útil?

Solución

El W3C tiene el siguiente: http://www.w3.org/WAI/ER/WD- AERT / # color de contraste

Si sólo está haciendo el texto negro o blanco, utilice el cálculo brillo del color anterior. Si es inferior a 125, utilizar el texto blanco. Si es 125 o superior, utilizar el texto negro.

editar 1: sesgo hacia el texto negro. :)

editar 2: La fórmula para uso es ((valor de Red * 299) + (valor verde * 587) + (valor azul * 114)) / 1000

.

Otros consejos

Aquí está una (3) de extensión Swift para llevar a cabo esta comprobación.

Esta extensión funciona con colores en escala de grises. Sin embargo, si va a crear todos los colores RGB con el inicializador y no utilizar el construido en colores como el UIColor.black y UIColor.white, luego, posiblemente, puede eliminar las comprobaciones adicionales.

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)
    }
}

Pruebas:

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")
}

Nota: Se ha actualizado para Swift 3 07/12/18

Uso de la respuesta de Erik Nedwidek, me ocurrió con ese pequeño fragmento de código para una fácil inserción.

- (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];
}

Swift3

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
}

Mi solución a este problema en una categoría (extraído de otras respuestas aquí). También funciona con colores en escala de grises, que en el momento de escribir ninguna de las otras respuestas hacen.

@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

Swift 4 Versión

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)
    }
}

Más simple extensión Swift 3:

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 prefiere la versión de bloque:

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;
};

Por todo lo que no es de color grisáceo, el inverso RGB de un color es generalmente altamente contrastado con él. La demo simplemente invierte el color y elimina la saturación de ella (lo convierte en un color gris).

Sin embargo, la generación de un buen calmante combinación de colores es bastante complicado. Vistazo a:

http://particletree.com/notebook/calculating- color de contraste para la legibles en texto /

Tras método es hallazgo es de color claro u oscuro en un lenguaje basado en Swift de color blanco.

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
}

Tras método es hallazgo es de color claro u oscuro en Swift usando componentes de color.

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
}

Para mí usando solamente CGColorGetComponents no funcionó, me sale 2 componentes para UIColors como el blanco. Así que tengo que comprobar el color de spaceModel primero. Esto es lo que ocurrió con que terminó siendo la versión rápida de la respuesta de @ mattsven.

Espacio de color tomada de aquí: 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
    }

UIColor tiene el siguiente método para convertir a HSB espacio de color :

- (BOOL)getHue:(CGFloat *)hue saturation:(CGFloat *)saturation brightness:(CGFloat *)brightness alpha:(CGFloat *)alpha;

Si desea encontrar el brillo del color, he aquí algo de pseudo código:

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);
}

Si es> 0,5 es brillante, y por lo demás oscuro.

- (BOOL)isColorLight:(UIColor*)color
{
    CGFloat white = 0;
    [color getWhite:&white alpha:nil];
    return (white >= .5);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top