Existe um método convencional para inverter os valores do NSCOLOR?
Pergunta
Estou procurando uma maneira de inverter arbitrário NSCOLOR Valores em tempo de execução, e não parece haver nenhum método interno para fazê-lo.
Estarei usando uma categoria para estender NSColor
do seguinte modo:
NSColor * invertedColor = [someOtherColor inverted];
Aqui está o protótipo do método de categoria que estou usando:
@implementation NSColor (MyCategories)
- (NSColor *)inverted
{
NSColor * original = [self colorUsingColorSpaceName:
NSCalibratedRGBColorSpace];
return ...?
}
@end
Alguém pode preencher os espaços em branco? Isso não precisa ser perfeito, mas eu gostaria que faça algum sentido. ou seja:
[[[NSColor someColor] inverted] inverted]
resultaria em uma cor muito próxima da cor original[[NSColor whiteColor] inverted]
estaria muito perto de[NSColor blackColor]
Cores invertidas estariam em lados opostos do roda de cores. (vermelho e verde, amarelo e violeta, etc.)
O valor alfa deve permanecer o mesmo que o original NSColor
. Estou apenas procurando inverter o cor, não a transparência.
Atualização 3: (agora em cor!)
Acontece que usar um cor complementar (Uma cor com um tom de 180 ° da tonalidade original) não é suficiente, pois o branco e o preto não têm um valor de matiz. Começando da resposta fornecida por Phoebus, foi isso que eu criei:
CGFloat hue = [original hueComponent];
if (hue >= 0.5) { hue -= 0.5; } else { hue += 0.5; }
return [NSColor colorWithCalibratedHue:hue
saturation:[original saturationComponent]
brightness:(1.0 - [original brightnessComponent])
alpha:[original alphaComponent]];
O tom ainda é girado 180 °, mas também inverto o componente de brilho para que as cores muito escuras se tornem muito brilhantes (e vice -versa). Isso cuida dos estojos em preto e branco, mas inverte quase todas as cores para preto (que viola minha regra de inversão dupla). Aqui estão os resultados:
Agora, Abordagem de Peter Hosey é muito mais simples e produz melhores resultados:
return [NSColor colorWithCalibratedRed:(1.0 - [original redComponent])
green:(1.0 - [original greenComponent])
blue:(1.0 - [original blueComponent])
alpha:[original alphaComponent]];
Em Swift 4.2:
extension NSColor {
func inverted() -> NSColor? {
return NSColor(calibratedRed: 1.0 - redComponent,
green: 1.0 - greenComponent,
blue: 1.0 - blueComponent,
alpha: alphaComponent)
}
}
Solução
Simples: os componentes são todos 0–1, então subtraia cada componente de 1 para obter o valor do complemento.
Exemplos:
- Vermelho = 1, 0, 0; complemento = 0, 1, 1 = ciano
- Amarelo = 1, 1, 0; complemento = 0, 0, 1 = azul
- Branco = 1, 1, 1; complemento = 0, 0, 0 = preto
- Laranja profunda = 1, 0,25, 0; complemento = 0, 0,75, 1 = azul -céu
Como você pode adivinhar, esta é uma operação simétrica. Inverter o inverso vai te levar exatamente a cor que você começou.
Outras dicas
Pelo que você descreve, parece que o que você realmente quer é uma função encontrar o complemento de uma cor, não é inverso. Inverter significa algo diferente nesse contexto.
Aqui está uma pergunta de Stackoverflow sobre complementos em JavaScript. Talvez parte do código seja adaptável?
Aqui são algumas informações interessantes e potencialmente úteis sobre as várias maneiras pelas quais a cor pode ser trabalhada em espaços de cores de cacau. Pelo que parece aqui, se você pode usar o espaço de cores HSV, o complemento de uma cor pode ser encontrado simplesmente tomando hue > 179 ? hue -= 180 : hue = += 180
, uma vez que os tons são definidos ao redor da roda de cores em um círculo completo.
Aqui está algum oneliner com Setter Custom (Alpha não é revertido!):
-(void)setReverseFontColor:(UIColor *)reverseFontColor {
_reverseFontColor = [AppSingleStyle reversedColorFromOriginal:reverseFontColor];
}
+(UIColor*)reversedColorFromOriginal:(UIColor*)originalColor {
return [UIColor colorWithRed:(1-CGColorGetComponents(originalColor.CGColor)[0]) green:(1-CGColorGetComponents(originalColor.CGColor)[1]) blue:(1-CGColorGetComponents(originalColor.CGColor)[2]) alpha:CGColorGetAlpha(originalColor.CGColor)];
}