2012-10-03 8 views
7

Ayer me encontré con una situación en la que necesitaba aligerar un UIColor, así que creé una categoría y agregué un método lighten. Pensé que sería sencillo multiplicar el valor por cada componente del color, pero mis greens comenzaron a ponerse amarillos, así que sabía que tenía que ser más complicado.Aligerar un UIColor

La solución que se me ocurrió fue convertir de sRGB a Linear, multiplicar el color y luego convertir de nuevo. Esto parece funcionar, pero no estoy seguro de si es "correcto". No pude encontrar nada en los documentos que indicaran que UIColor estaba en el espacio sRGB. Tampoco soy científico del color, así que solo tengo un conocimiento rudimentario de las matemáticas involucradas.

De todos modos aquí está mi código, estoy pidiendo una revisión por pares y para ver si alguien tiene una mejor comprensión de la modificación de UIColors.

CGFloat sRGB2Linear(CGFloat x){ 
    CGFloat a = 0.055; 
    if(x <= 0.04045){ 
     return x * (1.0/12.92); 
    }else{ 
     return pow((x + a) * (1.0/(1 + a)), 2.4); 
    } 
} 

CGFloat linear2sRGB(CGFloat x){ 
    CGFloat a = 0.055; 
    if(x <= 0.0031308){ 
     return x * 12.92; 
    }else{ 
     return (1 + a) * pow(x, 1/2.4) - a; 
    } 
} 

- (UIColor *)lighten:(CGFloat)value{ 
    const CGFloat *components = CGColorGetComponents([self CGColor]); 
    CGFloat newR = (sRGB2Linear(components[0])+1)*value; 
    CGFloat newG = (sRGB2Linear(components[1])+1)*value; 
    CGFloat newB = (sRGB2Linear(components[2])+1)*value; 
    newR = MAX(0, MIN(1, linear2sRGB(newR))); 
    newG = MAX(0, MIN(1, linear2sRGB(newG))); 
    newB = MAX(0, MIN(1, linear2sRGB(newB))); 
    return [UIColor colorWithRed:newR green:newG blue:newB alpha:components[3]]; 
} 

Respuesta

4

Puede trabajar con matiz, saturación y brillo.

obtener los valores viejos usando

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

continuación, ajustar el brillo, y la construcción de un nuevo color:

- (UIColor *)initWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha 

Tenga en cuenta que usted necesita para pasar punteros a la primera función.

+0

Si el color es escala de grises, no funciona. – ozgur

24

Esta es mi solución iOS5 + para hacer los cambios de brillo relativos fácilmente (aclarar y oscurecer todo-en-uno):

+ (UIColor*)changeBrightness:(UIColor*)color amount:(CGFloat)amount 
{ 

    CGFloat hue, saturation, brightness, alpha; 
    if ([color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) { 
     brightness += (amount-1.0); 
     brightness = MAX(MIN(brightness, 1.0), 0.0); 
     return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha]; 
    } 

    CGFloat white; 
    if ([color getWhite:&white alpha:&alpha]) { 
     white += (amount-1.0); 
     white = MAX(MIN(white, 1.0), 0.0); 
     return [UIColor colorWithWhite:white alpha:alpha]; 
    } 

    return nil; 
} 

Se invoca este modo:

[self changeBrightness:someUiColor amount:1.1] 

Usando 1.1 que aumentará el brillo en un 10%; 0.9 disminuirá el brillo en un 10%. Tenga en cuenta que el 10% es relativo al blanco puro (es decir, 10% es siempre un aumento de .1 en el brillo). Este es el comportamiento esperado si desea un aumento porcentual para aclarar u oscurecer los colores de forma consistente independientemente de su brillo inicial.

+0

Excelente código. Gracias por compartir. –

0

He mejorado el método de Ank para permitir la modificación de la saturación y el tono también.

La entrada se trata como porcentaje, por lo que b de 1.0 es igual a 100% (sin cambios). Para debilitar el brillo en un 30%, configure b en 0.7.

+ (UIColor*)changeColor:(UIColor*)color brightness:(CGFloat)b saturation:(CGFloat)s hue:(CGFloat)h 
{ 

    CGFloat hue, saturation, brightness, alpha; 
    if ([color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) { 
     brightness *= b; 
     brightness = MAX(MIN(brightness, 1.0), 0.0); 
     saturation *= s; 
     saturation = MAX(MIN(saturation, 1.0), 0.0); 
     hue *= h; 
     hue = MAX(MIN(hue, 1.0), 0.0); 
     return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha]; 
    } 

    CGFloat white; 
    if ([color getWhite:&white alpha:&alpha]) { 
     white += (b-1.0); 
     white = MAX(MIN(b, 1.0), 0.0); 
     return [UIColor colorWithWhite:white alpha:alpha]; 
    } 

    return nil; 
} 
0

tratar

- (UIColor *)mixColorWithWhiteAndAlpha:(CGFloat)alpha { 
    CGFloat r, g, b, a; 
    if ([self getRed:&r green:&g blue:&b alpha:&a]) 
     return [UIColor colorWithRed:r + (1 -r) * alpha 
           green:g + (1 -g) * alpha 
           blue:b + (1 -b) * alpha 
           alpha:a]; 
    return nil; 
} 

que deben regresar de color blanco mezclado con su color

lo que puede establecer alfa a 0,2 y creo que va a estar bien

0

respuesta de Kof en Swift :

extension UIColor { 
    public func changeBrightness(b: CGFloat, saturation s: CGFloat = 1.0, hue h: CGFloat = 1.0) -> UIColor? { 
     var hue : CGFloat = 0.0 
     var saturation : CGFloat = 0.0 
     var brightness : CGFloat = 0.0 
     var alpha : CGFloat = 0.0 

     if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) { 
      brightness *= b 
      brightness = max(min(brightness, 1.0), 0.0) 
      saturation *= s 
      saturation = max(min(saturation, 1.0), 0.0) 
      hue *= h 
      hue = max(min(hue, 1.0), 0.0) 

      return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha) 
     } 

     var white: CGFloat = 0.0 
     if self.getWhite(&white, alpha: &alpha) { 
      white += (b - 1.0) 
      white = max(min(b, 1.0), 0.0) 

      return UIColor(white: white, alpha: alpha) 
     } 

     return nil 
    } 
} 
0
- (UIColor *)changeBrightnessToPercentage:(CGFloat)percentage { 
    CGFloat hue, saturation, brightness, alpha; 
    if ([self getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) { 
     brightness += (percentage - 1.0); 
     brightness = MAX(MIN(brightness, 1.0), 0.0); 
     return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha]; 
    } 

    CGFloat white; 
    if ([self getWhite:&white alpha:&alpha]) { 
     white += (percentage - 1.0); 
     white = MAX(MIN(white, 1.0), 0.0); 
     return [UIColor colorWithWhite:white alpha:alpha]; 
    } 

    return nil; 
} 

== 1.0 es el color proporcionado,> 1.0 es más claro y < 1.0 es el más oscuro.

Cuestiones relacionadas