जांचें कि क्या यूआईसीरोल अंधेरा या उज्ज्वल है?


107

मुझे यह निर्धारित करने की आवश्यकता है कि क्या चयनित UIColor (उपयोगकर्ता द्वारा उठाया गया) गहरा या उज्ज्वल है, इसलिए मैं बेहतर पठनीयता के लिए, उस रंग के शीर्ष पर बैठने वाले पाठ की एक पंक्ति का रंग बदल सकता हूं।

यहाँ एक उदाहरण फ्लैश / एक्टीस्क्रिप्ट (डेमो के साथ): http://web.archive.org/web/2010010202024448/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");
    }
}

एक बार फिर से धन्यवाद :)


कुछ रंगों की तरह लगता है कि 3 घटक नहीं हैं, जैसे कि UIColor.black।
ग्लेन होव्स

जवाबों:


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]);अल्फा सहित रंग घटकों की एक सरणी प्राप्त करने के लिए उपयोग कर सकते हैं । डॉक्स निर्दिष्ट नहीं करते हैं कि वे किस क्रम में हैं, लेकिन मुझे लगता है कि यह लाल, हरा, नीला, अल्फा होगा। इसके अलावा, डॉक्स से, "सरणी का आकार रंग के लिए रंग स्थान के घटकों की संख्या से एक अधिक है।" - यह क्यों नहीं कहते ...
जसारीन

यह अजीब है ... का उपयोग करते हुए: NSArray * घटक = (NSArray *) CGColorGetCompords (newColor.CGColor); NSLog (@ "मेरे रंग घटक% f% f% f% f", घटक [0], घटक [1], घटक [2], घटक [3]; सिर्फ यह देखने के लिए कि क्या मैं मान प्राप्त कर सकता हूं, ऐसा लगता है कि केवल 0 इंडेक्स में बदलाव हुआ है, बाकी सभी वही रहेंगे, चाहे मैं कोई भी रंग चुनूं। कोई विचार क्यों?
आंद्रे

समझ गया। आप NSArray का उपयोग नहीं कर सकते। इसके बजाय इसका उपयोग करें: const CGFloat * Components = CGColorGetCompords (newColor.CGColor); इसके अलावा, आदेश है: लाल घटक है [0]; हरे रंग के घटक हैं [1]; नीला घटक है [2]; अल्फा घटक हैं [3];
आंद्रे

आह, मेरी बुर। मैंने सोचा कि यह एक सी सरणी नहीं, एक CFArrayRef लौटा। माफ़ करना!
जसारीन

44

इस चेक को करने के लिए यहां एक स्विफ्ट (3) एक्सटेंशन है।

यह एक्सटेंशन ग्रेस्केल रंगों के साथ काम करता है। हालांकि, अगर आप आरजीबी प्रारंभकर्ता के साथ अपने सभी रंग का निर्माण कर रहे हैं और का उपयोग नहीं करता है, तो इस तरह के रूप रंग में बनाया गया 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")
}

नोट: स्विफ्ट 3 12/7/18 को अपडेट किया गया


6
बहुत अच्छा काम करता है। स्विफ्ट 2.0 के साथ - मुझे चमक गणना के लिए एक कंपाइलर त्रुटि मिली: "अभिव्यक्ति उचित समय में हल करने के लिए बहुत जटिल थी; अभिव्यक्ति को अलग-अलग उप-अभिव्यक्तियों में तोड़ने पर विचार करें"। मैंने इसे टाइप करके तय किया: "चलो चमक = ((([[0] * 299.0) घटक CGFloat के रूप में) + ((घटक [1] * 587.0) CGFloat के रूप में) + ((घटक [2] * 114.0) CGFloat के रूप में ) / (1000.0 CGFloat के रूप में) "
GK100

1
मैं स्विफ्ट 2.1 के साथ एक ही मुद्दा था। मैंने इस मुद्दे को केवल उन तक पहुँचने के बजाय घटकों के लिए चर बनाकर हल किया components[0]। जैसे:let componentColorX: CGFloat = components[1]
पेट्रिट्ज

1
Xcode मुझे चमक बताती है = "अभिव्यक्ति उचित समय में हल करने के लिए बहुत जटिल थी, अभिव्यक्ति को अलग-अलग उप-अभिव्यक्तियों में तोड़ने पर विचार करें"
daidai

daiai, बस अभिव्यक्ति को सरल। अंत में विभाजन अनावश्यक है। हमें 0 - 1. श्रेणी में काम करने की आवश्यकता नहीं है। 1000 से विभाजित न करें, फिर यह जांचें कि क्या मान 500 के बजाय है।
aronspring

32

एरिक नेडवाइडक के उत्तर का उपयोग करते हुए, मैं आसान समावेश के लिए कोड के उस छोटे स्निपेट के साथ आया।

- (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] सेट किया, यह डार्कस्कोर = 149.685 देता है। क्या आप बता सकते हैं कि ऐसा क्यों हो रहा है?
डिवाइनडेर्ट

3
यह कोड गैर-RGB रंगों के साथ काम नहीं करेगा जैसे कि UIColor whiteColor, grayColor, blackColor
राम नवमी

@ श्राद्ध क्यों है? या क्यों नहीं कर रहे हैं सफेद रंग, ग्रे रंग और काले रंग आरजीबी रंग?
Mattsven

1
@rmaddy मैं RGB रंग अंतरिक्ष बनाम ग्रेस्केल में रंगों के बीच के अंतर को कैसे बता सकता हूं?
Mattsven

1
@ कामदेव नेवमिन्द! मदद के लिए धन्यवाद - 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
}

मेरे लिए यह सबसे अच्छा है। तुम भी अपनी आवश्यकताओं के अनुरूप चेक में सफेद की सीमा निर्धारित कर सकते हैं और सुपर सरल और देशी है। धन्यवाद।
एंड्रियासेंडा 7

9

स्विफ्ट 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 प्रतिनिधित्व नहीं है।
10

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

गैर आरजीबी रंगों का अच्छा संचालन - एक आकर्षण की तरह काम करता है।
हाटाइक

5

सरल स्विफ्ट 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 प्रतिनिधित्व नहीं है।
10

सच! आप रंग को हेक्स-स्ट्रिंग में परिवर्तित कर सकते हैं और फिर उस के लिए यूआईसीकलर में वापस आ सकते हैं।
सनकास

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

सब कुछ जो भूरा नहीं है, एक रंग का आरजीबी व्युत्क्रम आमतौर पर इसके साथ अत्यधिक विपरीत होता है। डेमो सिर्फ रंग को निष्क्रिय कर देता है और इसे असंतृप्त करता है (इसे ग्रे में परिवर्तित करता है)।

लेकिन रंगों का एक अच्छा सुखदायक संयोजन उत्पन्न करना काफी जटिल है। की ओर देखें :

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


1
यदि केवल उस का एक iPhone संस्करण था: D
आंद्रे

तो अगर मुझे एक रंग के RGB मान मिले (जो मुझे नहीं पता कि कैसे करना है) और उन मूल्यों के व्युत्क्रम के साथ एक नया रंग बनाया, जो कि बहुत ही बुनियादी स्तर पर काम करना चाहिए?
आंद्रे

2

निम्नलिखित विधि है रंग सफेद या सफेद रंग पर आधारित स्विफ्ट भाषा में हल्का या गहरा है।

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
}

निम्नलिखित विधि है रंग रंग प्रकाश का उपयोग कर स्विफ्ट में हल्का या गहरा है।

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

मेरे लिए केवल CGColorGetCompords का उपयोग करने से काम नहीं चला, मुझे सफेद जैसे UIColors के लिए 2 घटक मिलते हैं। इसलिए मुझे पहले कलर स्पेसमॉडल की जांच करनी होगी। यह वही है जो मैं खत्म हो गया है @ मैट्सवेन के उत्तर का स्विफ्ट संस्करण।

यहां से लिया गया रंगीन स्थान: 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 रंग इस कोड के साथ काम नहीं करेगा।
रैम्डडी

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
आप प्रत्येक रंग को समान रूप से नहीं कर सकते। हमारी आंखों में नीले रंग के खिलाफ एक पूर्वाग्रह है और कुछ हद तक लाल है।
एरिक नेडवाइडक

@ErikNedwidek: काफी साफ है, बस एक रंग की चमक के लिए पूछा गया सवाल :)
ब्रायन डेनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.