检查 UIColor 是黑色还是亮色?

我需要确定所选择的 UIColor (由用户选择)是深色还是亮色,这样我就可以更改位于该颜色顶部的一行文本的颜色,以便提高可读性。

下面是 Flash/Actionscript 中的一个示例(附带演示) : Http://web.archive.org/web/20100102024448/http://theflashblog.com/?p=173

有什么想法吗?

干杯, 安德烈

更新

感谢大家的建议,以下是工作代码:

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

再次感谢:)

30989 次浏览

对于所有不是灰色的东西,颜色的 RGB 反转通常与它形成强烈的对比。 演示只是反转颜色和去饱和(转换为灰色)。

但是产生一个舒缓的颜色组合是相当复杂的。 看看:

Http://particletree.com/notebook/calculating-color-contrast-for-legible-text/

如果你想找到颜色的亮度,这里有一些伪代码:

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

如果它大于0.5,它就是明亮的,否则就是黑暗的。

W3C 有以下几点: Http://www.w3.org/wai/er/wd-aert/#color-contrast

如果您只使用黑色或白色文本,请使用上面的颜色亮度计算。如果低于125,则使用白色文本。如果是125或以上,则使用黑色文本。

编辑1: 偏向黑色文本。 :)

编辑2: 使用的公式是((红色值 * 299) + (绿色值 * 587) + (蓝色值 * 114))/1000。

Using Erik Nedwidek's answer, I came up with that little snippet of code for easy inclusion.

- (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];
}
- (BOOL)isColorLight:(UIColor*)color
{
CGFloat white = 0;
[color getWhite:&white alpha:nil];
return (white >= .85);
}

新增 Swift 5版本:

var white: CGFloat = 0.0
color.getWhite(&white, alpha: nil)
return white >= .85 // Don't use white background

如果你喜欢块版本:

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

下面是执行此检查的 Swift (3)扩展。

This extension works with greyscale colors. However, if you are creating all your colors with the RGB initializer and not using the built in colors such as UIColor.black and UIColor.white, then possibly you can remove the additional checks.

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

测试:

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

Note: Updated to Swift 3 12/7/18

我对这个问题的解决方案在一个类别(从这里的其他答案)。也适用于灰度颜色,在写作的时候没有其他的答案。

@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 语言中找出颜色是亮还是暗。

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
}

下面的方法是在 Swift 中使用颜色分量查找颜色是亮还是暗。

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
}

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
}

更简单的 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
}
}

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

对于我来说,只使用 CGColorGetComponent 不起作用,我得到了两个 UIColors 组件,比如白色。所以我必须先检查颜色空间模型。 这就是我想出来的答案,结果变成了@mattsven 回答的快速版本。

Color space taken from here: 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 有以下方法可以转换为 HSB color space:

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