Check If Uicolor Is Dark or Bright

Check if UIColor is dark or bright?

W3C has the following:
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.

edit 1: bias towards black text. :)

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

Determine if color is light or dark?

I haven't tested this, but it may work for you...

-(BOOL) isLightColor:(UIColor*)clr {
CGFloat white = 0;
[clr getWhite:&white alpha:nil];
return (white >= 0.5);
}

Detect Color type (dark or light)

I tried the colors in your pictures:

Sample Image
Sample Image

And I got exactly the expected answers:

isDarkBackground(color:Color(.sRGB, red: 0.346, green: 0.339, blue: 0.836, opacity: 1))
isDarkBackground(color:Color(.sRGB, red: 0.350, green: 0.784, blue: 0.987, opacity: 1))

// 0.37637156163454055, true
// 0.7063881726026535, false

So perhaps the input color in your real code is not the color you think it is.

Also there might be some issue with your understanding of what luminance is. I tried your isDarkBackground with Color.blue and I got your 0.41437413557767866 (which is true). But now try it with Color.yellow; you get 0.7847599958539009 (which is false).

So your code is working perfectly — for what it is. Perhaps the formula you are using is not the formula you really wanted, but the formula itself is behaving correctly.

Get dark style of UIColor

You can use UIColor method func resolvedColor(with traitCollection: UITraitCollection) -> UIColor and select the desired trait collection:

extension UIColor {
var dark: UIColor { resolvedColor(with: .init(userInterfaceStyle: .dark)) }
var light: UIColor { resolvedColor(with: .init(userInterfaceStyle: .light)) }
}


Example

let systemPurple = UIColor.systemPurple   // r 0,686 g 0,322 b 0,871 a 1,0
systemPurple.dark // r 0,749 g 0,353 b 0,949 a 1,0
systemPurple.light // r 0,686 g 0,322 b 0,871 a 1,0

How to detect if Color is white or black in Swift

You can get the HSB brightness component from Color by first converting it to a UIColor. Here's a little extension I made to do this:

import UIKit
import SwiftUI

extension Color {
enum Brightness {
case light, medium, dark, transparent

private enum Threshold {
static let transparent: CGFloat = 0.1
static let light: CGFloat = 0.75
static let dark: CGFloat = 0.3
}

init(brightness: CGFloat, alpha: CGFloat) {
if alpha < Threshold.transparent {
self = .transparent
} else if brightness > Threshold.light {
self = .light
} else if brightness < Threshold.dark {
self = .dark
} else {
self = .medium
}
}
}

var brightness: Brightness {
var b: CGFloat = 0
var a: CGFloat = 0
let uiColor = UIColor(self)
uiColor.getHue(nil, saturation: nil, brightness: &b, alpha: &a)
return .init(brightness: b, alpha: a)
}
}

Color.white.brightness // .light
Color.gray.brightness // .medium
Color.black.brightness // .dark
Color.clear.brightness // .transparent

The thresholds are ad hoc and untested for any real purpose. The UIColor.init used here also requires iOS 14+ (https://developer.apple.com/documentation/uikit/uicolor/3550899-init).

How to get explicitly light or dark color from ColorSet?

You can use UIColor.resolvedColor(with:)

Tested:

let color = UIColor(named: "Color")?.resolvedColor(with: UITraitCollection(userInterfaceStyle: .light))
let rgb = color!.cgColor.components

Get Slightly Lighter and Darker Color from UIColor


- (UIColor *)lighterColorForColor:(UIColor *)c
{
CGFloat r, g, b, a;
if ([c getRed:&r green:&g blue:&b alpha:&a])
return [UIColor colorWithRed:MIN(r + 0.2, 1.0)
green:MIN(g + 0.2, 1.0)
blue:MIN(b + 0.2, 1.0)
alpha:a];
return nil;
}

- (UIColor *)darkerColorForColor:(UIColor *)c
{
CGFloat r, g, b, a;
if ([c getRed:&r green:&g blue:&b alpha:&a])
return [UIColor colorWithRed:MAX(r - 0.2, 0.0)
green:MAX(g - 0.2, 0.0)
blue:MAX(b - 0.2, 0.0)
alpha:a];
return nil;
}

Use it like this:

UIColor *baseColor = // however you obtain your color
UIColor *lighterColor = [self lighterColorForColor:baseColor];
UIColor *darkerColor = [self darkerColorForColor:baseColor];

EDIT: as @Anchu Chimala pointed out, for maximum flexibility, these methods should be implemented as an UIColor category. Also, from @Riley's idea, it may be a better idea to make the color proprtionally darker or lighter instead of adding or subtracting constant values. As @jrturton pointed out, it's not necessary to manipulate the RGB components; it's better to modify the brightness property itself. All in all:

@implementation UIColor (LightAndDark)

- (UIColor *)lighterColor
{
CGFloat h, s, b, a;
if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
return [UIColor colorWithHue:h
saturation:s
brightness:MIN(b * 1.3, 1.0)
alpha:a];
return nil;
}

- (UIColor *)darkerColor
{
CGFloat h, s, b, a;
if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
return [UIColor colorWithHue:h
saturation:s
brightness:b * 0.75
alpha:a];
return nil;
}
@end

UIColor comparison

You could install this Category for extending UIColor for knowing HSV/HSB and compare [aUIColor brightness]

Edit:

I found the same code in some github-hosted project, made a gist of it: https://gist.github.com/1252197


#import "UIColor-HSVAdditions.h"

@implementation UIColor (UIColor_HSVAdditions)
+(struct hsv_color)HSVfromRGB:(struct rgb_color)rgb
{
struct hsv_color hsv;

CGFloat rgb_min, rgb_max;
rgb_min = MIN3(rgb.r, rgb.g, rgb.b);
rgb_max = MAX3(rgb.r, rgb.g, rgb.b);

hsv.val = rgb_max;
if (hsv.val == 0) {
hsv.hue = hsv.sat = 0;
return hsv;
}

rgb.r /= hsv.val;
rgb.g /= hsv.val;
rgb.b /= hsv.val;
rgb_min = MIN3(rgb.r, rgb.g, rgb.b);
rgb_max = MAX3(rgb.r, rgb.g, rgb.b);

hsv.sat = rgb_max - rgb_min;
if (hsv.sat == 0) {
hsv.hue = 0;
return hsv;
}

if (rgb_max == rgb.r) {
hsv.hue = 0.0 + 60.0*(rgb.g - rgb.b);
if (hsv.hue < 0.0) {
hsv.hue += 360.0;
}
} else if (rgb_max == rgb.g) {
hsv.hue = 120.0 + 60.0*(rgb.b - rgb.r);
} else /* rgb_max == rgb.b */ {
hsv.hue = 240.0 + 60.0*(rgb.r - rgb.g);
}

return hsv;
}
-(CGFloat)hue
{
struct hsv_color hsv;
struct rgb_color rgb;
rgb.r = [self red];
rgb.g = [self green];
rgb.b = [self blue];
hsv = [UIColor HSVfromRGB: rgb];
return (hsv.hue / 360.0);
}
-(CGFloat)saturation
{
struct hsv_color hsv;
struct rgb_color rgb;
rgb.r = [self red];
rgb.g = [self green];
rgb.b = [self blue];
hsv = [UIColor HSVfromRGB: rgb];
return hsv.sat;
}
-(CGFloat)brightness
{
struct hsv_color hsv;
struct rgb_color rgb;
rgb.r = [self red];
rgb.g = [self green];
rgb.b = [self blue];
hsv = [UIColor HSVfromRGB: rgb];
return hsv.val;
}
-(CGFloat)value
{
return [self brightness];
}
@end

How do I check if a hex color in an NSString is light or dark in Objective C?

See Formula to determine brightness of RGB color.

Hex colors are usually RRGGBB or RRGGBBAA (alpha).

how to convert hexadecimal to RGB

To get three ints instead of a UIColor, you can modify the answer from that to:

void rgb_from_hex(char *hexstring, int *red, int *green, int *blue) {
// convert everything after the # into a number
long x = strtol(hexstring+1, NULL, 16);

// extract the bytes
*blue = x & 0xFF;
*green = (x >> 8) & 0xFF;
*red = (x >> 16) & 0xFF;
}

// The above function is used like this:
int main (int argc, const char * argv[])
{
int r,g,b;
rgb_from_hex("#123456", &r, &g, &b);
printf("r=%d, g=%d, b=%d\n", r, g, b);
}

(The function will probably only correctly handle RGB, not RGBA.)

Get lighter and darker color variations for a given UIColor


Updated

Use below UIColor Extension:

extension UIColor {

func lighter(by percentage: CGFloat = 30.0) -> UIColor? {
return self.adjust(by: abs(percentage) )
}

func darker(by percentage: CGFloat = 30.0) -> UIColor? {
return self.adjust(by: -1 * abs(percentage) )
}

func adjust(by percentage: CGFloat = 30.0) -> UIColor? {
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) {
return UIColor(red: min(red + percentage/100, 1.0),
green: min(green + percentage/100, 1.0),
blue: min(blue + percentage/100, 1.0),
alpha: alpha)
} else {
return nil
}
}
}

Usage:

let color = UIColor(red:0.96, green:0.54, blue:0.10, alpha:1.0)
color.lighter(30) // returns lighter color by 30%
color.darker(30) // returns darker color by 30%

instead of .lighter() and .darker(), you can use .adjust() with positive values for lightening and negative values for darkening

color.adjust(-30) // 30% darker color
color.adjust(30) // 30% lighter color

Output:

Sample Image



Related Topics



Leave a reply



Submit