iGio90
iGio90

Reputation: 3291

Check if color is dark or light in Android

as per title, my question is: Does Android provide any way to analyze/determine if a color (that will be obviously dynamic for the purpose) is light or dark?

Upvotes: 70

Views: 27358

Answers (8)

Sergio
Sergio

Reputation: 30645

In Kotlin using extension function on Int type and with a darkness threshold parameter it can look like the following:

/**
 * Determines if this color is dark.
 * @param threshold - min darkness value; the higher the value, the darker the color;
 * float value between 0.0 and 1.0.
 */
fun Int.isColorDark(@FloatRange(from = 0.0, to = 1.0) threshold: Float = 0.9f): Boolean {
    val darkness = 1 - (Color.red(this) * 0.299 + Color.green(this) * 0.587 + Color.blue(this) * 0.114) / 255
    return darkness >= threshold
}

Upvotes: 0

Amir
Amir

Reputation: 1815

If you want to include alpha channel in calculations:

fun isColorDark(color: Int): Boolean {
    val darkness = (1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255) * (Color.alpha(color) / 255)
    return darkness >= 0.5
}

Upvotes: 0

theZ3r0CooL
theZ3r0CooL

Reputation: 227

Simplifying the accepted answer a little

public boolean isColorDark(int color){
    final double darkness = 1-(0.299*Color.red(color) + 0.587*Color.green(color) + 0.114*Color.blue(color))/255;
    return !(darkness<0.5);
}

Upvotes: 0

C&#237;cero Moura
C&#237;cero Moura

Reputation: 2333

Another solution:

private static final int BRIGHTNESS_THRESHOLD = 130;

    /**
     * Calculate whether a color is light or dark, based on a commonly known
     * brightness formula.
     *
     * @see {@literal http://en.wikipedia.org/wiki/HSV_color_space%23Lightness}
     */
    public static boolean isColorDark(int color) {
        return ((30 * Color.red(color) +
                59 * Color.green(color) +
                11 * Color.blue(color)) / 100) <= BRIGHTNESS_THRESHOLD;
    }

Upvotes: 1

krossovochkin
krossovochkin

Reputation: 12122

In case one would like to find out whether background color is light or dark to determine what color to use for text drawn on top of it (white or black) – calculating luminance won't provide you correct value in all the cases.

Consider you have background color: #7f6fad. If you check its luminance (via ColorUtils#calculateLuminance) you'll get: 0.1889803503770053, which is below 0.5 and therefore should be considered as dark following that logic.

But if you follow WCAG you'll see that for general text contrast should be at least 4.5:1.

ColorUtils has method calculateContrast which will give the following results:

  • For white text color: 4.393666669010922
  • For black text color: 4.779607007540106

One can see that contrast which white text gives is not enough, while black is good. Therefore if you'd like to check what color to draw on top of some generic background color it is better to check contrasts instead:

@ColorInt
fun getContrastColor(@ColorInt color: Int): Int {
    val whiteContrast = ColorUtils.calculateContrast(Color.WHITE, color)
    val blackContrast = ColorUtils.calculateContrast(Color.BLACK, color)

    return if (whiteContrast > blackContrast) Color.WHITE else Color.BLACK
}

Upvotes: 14

Robyer
Robyer

Reputation: 4852

If you use support library v4 (or AndroidX), you can use ColorUtils.calculateLuminance(color), which returns luminance of color as float between 0.0 and 1.0.

So you can do something like:

boolean isDark(int color) {
    return ColorUtils.calculateLuminance(color) < 0.5;
}

See:

Note since Android API 24 there is also method: Color.luminance(color).

Upvotes: 103

Brandon Bahret
Brandon Bahret

Reputation: 163

public float getLightness(int color) {
    int red   = Color.red(color);
    int green = Color.green(color);
    int blue  = Color.blue(color);

    float hsl[] = new float[3];
    ColorUtils.RGBToHSL(red, green, blue, hsl);
    return hsl[2];
}

One could easily use the ColorUtils to check the lightness of a color.

if (getLightness(color) < 0.5f ){
    // This color is too dark!
}

Upvotes: 7

adboco
adboco

Reputation: 2870

Android doesn't provide it, you can implement a method to determine this. Here a method to do that:

public boolean isColorDark(int color){
    double darkness = 1-(0.299*Color.red(color) + 0.587*Color.green(color) + 0.114*Color.blue(color))/255;
    if(darkness<0.5){
        return false; // It's a light color
    }else{
        return true; // It's a dark color
    }
}

Upvotes: 135

Related Questions