Contrast between label and background: determine if color is light or dark
Asked Answered
R

2

2

I have a barplot with labels in white. Sometimes the color of background is too light and the white label becomes illegible. I'm looking for a function that takes a color value and returns whether the color is dark or light. Then I can set the label color to white or black accordingly to obtain the best contrast against the background.

Realtor answered 22/3, 2018 at 19:49 Comment(4)
I'd prefer the black and white ... if I use grey then when the palette is gray the label will be again illegible.Realtor
Something like this maybe: #47281865. When asking for help, you should include a simple reproducible example with sample input and desired output that can be used to test and verify possible solutions.Honk
Also this function for calculating perceived brightness might help. trendct.org/2016/01/22/…. Don't know of any built-in implementation of it in R but it's clearly not too difficult to write into your own function.Honk
@Honk thank you for the comments. The solution in your first comment is specific to that problem. I will then make a function based on your second comment. I just dont like reinventing the wheel if there exist such a thing already.Realtor
C
10

Here's a strategy to implement picking a text color of black vs white based on the intensity scale in the (second) link provided by @MrFlick.

The blog cited a W3C publication: a standard formula for calculating the perceived brightness of a color that used an algorithm for RGB encoded colors:

 ((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000

The col2rgb function delivers a 3-row matrix which I multiply by the factors offered in that webpage. I used an example of "red" as a background color and the chosen text would then be "white"

 c( "black", "white")[  1+(sum( col2rgb("red") *c(299, 587,114))/1000 < 123) ]
[1] "white"

Implemented as a function:

isDark <- function(colr) { (sum( col2rgb(colr) * c(299, 587,114))/1000 < 123) }
isDark("red")
[1] TRUE
Custumal answered 22/3, 2018 at 20:12 Comment(2)
Just in case: in the function col2rgb("red") should be col2rgb(colr)Valuer
Thanks. Obvious when examined. Not so obvious when in a hurry.Custumal
H
1

You can also use farver::decode_colour to calculate luminance directly. This is the approach used by scales::show_col.

cols <- viridis::viridis(12)
hcl <- farver::decode_colour(cols, to = "hcl")
ifelse(hcl[, "l"] > 50, "black", "white") # cutoff between 0 and 100
Hubing answered 21/1, 2024 at 13:54 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.