iphone - util - Compruebe si UIColor es oscuro o brillante
nivel de desgaste bateria iphone (14)
Necesito determinar si un UIColor seleccionado (elegido por el usuario) es oscuro o brillante, por lo que puedo cambiar el color de una línea de texto que se encuentra encima de ese color, para una mejor legibilidad.
Aquí hay un ejemplo en Flash / Actionscript (con demostración): http://theflashblog.com/?p=173
¿Alguna idea?
Saludos, 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 :)
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
}
El siguiente método es encontrar el color claro u oscuro en el lenguaje Swift basado en el 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
}
El siguiente método es encontrar que el color es 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
}
Extensión Simpler 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
}
}
Mi solución a este problema en una categoría (extraída de otras respuestas aquí). También funciona con colores en escala de grises, que en el momento de escribir ninguna de las otras respuestas sí.
@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
Para mí, usar solo CGColorGetComponents no funcionó, obtengo 2 componentes para UIColors como el blanco. Así que primero tengo que verificar el color spaceModelo. Esto es lo que se me ocurrió que terminó siendo la versión rápida de la respuesta de @mattsven.
Espacio de color tomado de aquí: https://.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
}
Para todo lo que no es grisáceo, el inverso RGB de un color suele ser muy contrastado con él. La demostración simplemente invierte el color y lo desatura (lo convierte en gris).
Pero generar una agradable combinación de colores es bastante complicado. Mirar :
http://particletree.com/notebook/calculating-color-contrast-for-legible-text/
Si desea encontrar el brillo del color, aquí hay algún 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 oscuro.
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;
};
Usando la respuesta de Erik Nedwidek, se me ocurrió ese pequeño fragmento de código para facilitar su inclusió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];
}
Usar HandyUIKit hace que esto no sea obvio , por ejemplo:
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
Simplemente usar .hlca.luminance
en cualquier instancia de UIColor
le dará el valor correcto para la claridad percibida . La mayoría de los otros enfoques no toman en cuenta el hecho de que los humanos perciben diferentes colores (incluso cuando la saturación y el brillo son los mismos) a diferentes niveles de brillo . Los valores de luminance
tienen esto en cuenta.
Lea esta gran publicación de blog o la entrada de Wikipedia en el espacio de color LAB para obtener más información. También explicarán por qué el sistema de color HSB con su valor de brightness
es solo la mitad de la solución.
Solo como sugerencia: tenga en cuenta que el valor de luminance
del color verde puro es mucho mayor que en el color azul puro . Eso es simplemente porque los humanos perciben el azul puro como un color mucho más oscuro que el verde puro.
Versión 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)
}
}
W3C tiene lo siguiente: http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
Si solo está haciendo texto en blanco y negro, use el cálculo de brillo de color anterior. Si está por debajo de 125, use texto blanco. Si es 125 o superior, use texto negro.
edición 1: sesgo hacia el texto negro. :)
edición 2: La fórmula a usar es ((Valor rojo * 299) + (Valor verde * 587) + (Valor azul * 114)) / 1000.
Y aquí hay una extensión de Swift:
extension UIColor
{
func isLight() -> Bool
{
let components = CGColorGetComponents(self.CGColor)
let brightness = ((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000
if brightness < 0.5
{
return false
}
else
{
return true
}
}
}
- (BOOL)isColorLight:(UIColor*)color
{
CGFloat white = 0;
[color getWhite:&white alpha:nil];
return (white >= .5);
}