ios 检查 UIColor 是暗还是亮?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2509443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:03:09  来源:igfitidea点击:

Check if UIColor is dark or bright?

iosiphonexcodecolorsuicolor

提问by Andre

I need to determine whether a selected UIColor (picked by the user) is dark or bright, so I can change the color of a line of text that sits on top of that color, for better readability.

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

Here's an example in Flash/Actionscript (with demo): http://web.archive.org/web/20100102024448/http://theflashblog.com/?p=173

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

Any thoughts?

有什么想法吗?

Cheers, Andre

干杯,安德烈

UPDATE

更新

Thanks to everyone's suggestions, here's the working code:

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

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

Thanks once again :)

再次感谢 :)

采纳答案by Erik Nedwidek

W3C has the following: http://www.w3.org/WAI/ER/WD-AERT/#color-contrast

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

If you're only doing black or white text, use the color brightness calculation above. If it is below 125, use white text. If it is 125 or above, use black text.

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

edit 1: bias towards black text. :)

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

edit 2: The formula to use is ((Red value * 299) + (Green value * 587) + (Blue value * 114)) / 1000.

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

回答by josh-fuggle

Here is a Swift (3) extension to perform this check.

这是执行此检查的 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.blackand UIColor.white, then possibly you can remove the additional checks.

此扩展程序适用于灰度颜色。但是,如果要创建与RGB初始化所有的颜色,而不是使用内置的颜色,如UIColor.blackUIColor.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)
    }
}

Tests:

测试:

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

注意:更新到 Swift 3 12/7/18

回答by Remy Vanherweghem

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

使用 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];
}

回答by neoneye

Swift3

斯威夫特3

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
}

回答by mattsven

My solution to this problem in a category (drawn from other answers here). Also works with grayscale colors, which at the time of writing none of the other answers do.

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

@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

回答by Kaiyuan Xu

Swift 4 Version

斯威夫特 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)
    }
}

回答by Sunkas

Simpler Swift 3 extension:

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

回答by kakilangit

If you prefer the block version:

如果您更喜欢块版本:

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

回答by Lucho

For me using only CGColorGetComponents didn't worked, I get 2 components for UIColors like white. So I have to check the color spaceModel first. This is what I came up with that ended up being the swift version of @mattsven's answer.

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

Color space taken from here: https://stackoverflow.com/a/16981916/4905076

从这里获取的色彩空间: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
    }

回答by Cuddy

UIColor has the following method to convert to HSB color space:

UIColor 有以下方法可以转换为HSB 颜色空间

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