检查UIColor是暗还是亮?

And*_*dre 100 iphone xcode colors uicolor ios

我需要确定选定的UIColor(由用户选择)是暗还是亮,因此我可以更改位于该颜色顶部的文本行的颜色,以提高可读性.

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

有什么想法吗?

干杯,安德烈

UPDATE

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

- (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");
    }
}
Run Code Online (Sandbox Code Playgroud)

再次感谢 :)

Eri*_*dek 72

W3C具有以下内容:http: //www.w3.org/WAI/ER/WD-AERT/#color-contrast

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

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

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


jos*_*gle 35

这是执行此检查的Swift(3)扩展.

此扩展适用于灰度颜色.但是,如果使用RGB初始化程序创建所有颜色而不使用内置颜色(如UIColor.black和)UIColor.white,则可能会删除其他检查.

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

测试:

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")
}
Run Code Online (Sandbox Code Playgroud)

注意:已更新至Swift 3 12/7/18

  • 效果很好.使用Swift 2.0 - 我得到了亮度计算的编译器错误:"表达式太复杂,无法在合理的时间内解决;考虑将表达式分解为不同的子表达式".我通过添加类型修复它:"让亮度=((([[0]*299.0)作为CGFloat)+((组件[1]*587.0)作为CGFloat)+((组件[2]*114.0))作为CGFloat )/(1000.0作为CGFloat)" (5认同)

Rem*_*hem 31

使用Erik Nedwidek的答案,我想出了一小段代码,以便于包含.

- (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];
}
Run Code Online (Sandbox Code Playgroud)

  • 此代码不适用于非RGB颜色,例如`UIColor whiteColor,grayColor,blackColor`. (2认同)

neo*_*eye 29

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
}
Run Code Online (Sandbox Code Playgroud)


mat*_*ven 7

我在一个类别中解决这个问题(来自其他答案).也适用于灰度颜色,在撰写本文时,没有其他答案可以使用.

@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
Run Code Online (Sandbox Code Playgroud)


Kai*_* Xu 7

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)
    }
}
Run Code Online (Sandbox Code Playgroud)


Sun*_*kas 5

更简单的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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这可能不适用于像UIColor.white这样的默认系统颜色,因为它只有2个组件,它不是RGB表示. (2认同)

Luc*_*cho 5

对我来说,只使用 CGColorGetComponents 是行不通的,我得到了 2 个 UIColors 组件,比如白色。所以我必须先检查色彩空间模型。这就是我想出的,最终成为@mattsven 答案的快速版本。

色彩空间取自此处: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
    }
Run Code Online (Sandbox Code Playgroud)