UIColor가 어둡거나 밝은 지 확인하십시오.


107

선택한 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");
    }
}

다시 한번 감사합니다 :)


일부 색상에는 UIColor.black과 같은 세 가지 구성 요소가없는 것 같습니다.
Glenn Howes

답변:


75

W3C에는 다음이 있습니다. http://www.w3.org/WAI/ER/WD-AERT/#color-contrast

흑백 텍스트 만 수행하는 경우 위의 색상 밝기 계산을 사용하십시오. 125 미만이면 흰색 텍스트를 사용하십시오. 125 이상이면 검정색 텍스트를 사용하십시오.

편집 1 : 검정 텍스트쪽으로 편향. :)

편집 2 : 사용할 공식은 ((빨간색 값 * 299) + (녹색 값 * 587) + (파란색 값 * 114)) / 1000입니다.


색상의 빨강, 녹색 및 파랑 값을 얻는 방법을 알고 있습니까?
앙드레

NSArray *components = (NSArray *)CGColorGetComponents([UIColor CGColor]);알파를 포함한 색상 구성 요소의 배열을 얻는 데 사용할 수 있습니다 . 문서는 순서를 지정하지 않지만 빨강, 녹색, 파랑, 알파라고 가정합니다. 또한 문서에서 "배열의 크기는 색상에 대한 색상 공간의 구성 요소 수보다 하나 더 많습니다." -이유를 말하지 않습니다 ...
Jasarien

이상합니다 ... 사용 : NSArray * components = (NSArray *) CGColorGetComponents (newColor.CGColor); NSLog (@ "내 색상 구성 요소 % f % f % f % f", 구성 요소 [0], 구성 요소 [1], 구성 요소 [2], 구성 요소 [3]); 값을 얻을 수 있는지 확인하기 위해 0 인덱스 만 변경되고 다른 색상은 내가 선택한 색상에 관계없이 동일하게 유지됩니다. 왜 그런지 아세요?
앙드레

알았다. NSArray를 사용할 수 없습니다. 대신 사용하십시오. const CGFloat * components = CGColorGetComponents (newColor.CGColor); 또한 순서는 다음과 같습니다. 빨간색은 구성 요소 [0]입니다. 녹색은 구성 요소 [1]입니다. 파란색은 구성 요소 [2]입니다. 알파는 성분 [3]이고;
앙드레

아, 나쁘다. C 배열이 아닌 CFArrayRef를 반환했다고 생각했습니다. 죄송합니다!
Jasarien

44

다음은이 검사를 수행하는 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)
    }
}

테스트 :

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

참고 : Swift 3 12/7/18로 업데이트 됨


6
잘 작동합니다. Swift 2.0-밝기 계산에 대한 컴파일러 오류가 발생했습니다. "표현식이 너무 복잡해서 적절한 시간에 풀 수 없습니다. 표현식을 별개의 하위 표현식으로 분할하는 것을 고려하십시오." 다음 유형을 추가하여 수정했습니다. "let 밝기 = (((components [0] * 299.0) as CGFloat) + ((components [1] * 587.0) as CGFloat) + ((components [2] * 114.0))) as CGFloat ) / (1000.0 as CGFloat) "
GK100

1
Swift 2.1에서 동일한 문제가 발생했습니다. 을 사용하여 액세스하는 대신 구성 요소에 대한 변수를 생성하여이 문제를 해결했습니다 components[0]. 그렇게 :let componentColorX: CGFloat = components[1]
petritz 2015

1
엑스 코드 "는 표현이 적절한 시간에 해결하기에 너무 복잡, 고려는 별개의 하위 식으로 표현 깨고"= 나에게 밝기를 알려줍니다
다이 다이

daidai, 그냥 표현을 단순화하십시오. 마지막 부분은 불필요합니다. 0-1 범위에서 작업 할 필요는 없습니다. 1000으로 나누지 말고 값이 500보다 큰지 확인하십시오.
aronspring 2010 년

32

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

이 코드를 사용하고 완벽하게 작동했지만 [UIColor blackColor]를 설정하면 어두움 Score = 149.685를 반환합니다. 왜 이런 일이 일어나는지 설명해 주시겠습니까?
DivineDesert

3
이 코드는 UIColor whiteColor, grayColor, blackColor.
rmaddy

@rmaddy 왜 그럴까요? 또는 whiteColor, grayColor 및 blackColor RGB 색상이 아닌 이유는 무엇입니까?
mattsven 2015-04-21

1
@rmaddy RGB 색상 공간과 회색조의 색상 차이를 프로그래밍 방식으로 구분하려면 어떻게해야합니까?
mattsven

1
@maddy 신경 쓰지 마! 도움을 주셔서 감사합니다 - stackoverflow.com/questions/1099569/...
mattsven

31

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
}

저에게는 이것이 최고입니다. 필요에 맞게 수표에서 흰색 범위를 설정할 수도 있으며 매우 간단하고 기본입니다. 감사.
Andreas777

9

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

1
UIColor.white와 같은 기본 시스템 색상에는 2 개의 구성 요소 만 있고 RGB 표현이 아니므로 작동하지 않을 것입니다.
Skrew

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

비 RGB 색상의 멋진 처리-매력처럼 작동합니다.
hatunike

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

2
UIColor.white와 같은 기본 시스템 색상에는 2 개의 구성 요소 만 있고 RGB 표현이 아니므로 작동하지 않을 것입니다.
Skrew

진실! 색상을 16 진수 문자열로 변환 한 다음 다시 UIColor로 변환하여이를 고려할 수 있습니다.
Sunkas

3

블록 버전을 선호하는 경우 :

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

2

회색이 아닌 모든 색상의 경우 RGB 반전 색상이 일반적으로 대조됩니다. 데모는 색상을 반전하고 채도를 낮 춥니 다 (회색으로 변환).

그러나 멋진 차분한 색상 조합을 생성하는 것은 매우 복잡합니다. 보다 :

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


1
D : 해당의 아이폰 버전이 있었다면
앙드레

그렇다면 색상의 RGB 값 (어떻게해야할지 모르겠 음)을 얻고이 값의 역으로 ​​새 색상을 만들면 매우 기본적인 수준에서 작동해야합니까?
앙드레

2

다음 방법은 색상이 흰색을 기반으로 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
}

2

CGColorGetComponents 만 사용하는 경우 작동하지 않았으며 흰색과 같은 UIColors에 대한 두 가지 구성 요소를 얻습니다. 그래서 먼저 color spaceModel을 확인해야합니다. 이것은 @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
    }

2

UIColor에는 HSB 색상 공간 으로 변환하는 다음 메서드가 있습니다 .

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

1
- (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

1
UIColor회색조 색상 인 경우에만 작동합니다 . 임의의 RGB 색상은이 코드에서 작동하지 않습니다.
rmaddy

0

색상의 밝기를 찾으려면 다음과 같은 의사 코드가 있습니다.

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보다 크면 밝고 그렇지 않으면 어둡습니다.


2
각 색상에 똑같이 가중치를 적용 할 수 없습니다. 우리의 눈은 파란색에 대한 편견이 있고 덜 빨간색입니다.
Erik Nedwidek

@ErikNedwidek : 충분합니다. 질문은 단순히 색상의 밝기를 요청했습니다. :)
Bryan Denny
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.