Text color question

How to calculate the “value” of a background color to know if we should write the text in white or in black on top?

1 Like

thank you Sascha, but in xojo, we already have the Hue of the color
I wonder how to calculate the threshold that makes the eye see better when it’s written in black or white over a background of this color

Public Function ContrastColor(BackgroundColor As Color) As Color
  Var c As Integer
  Var luminance As Double
  
  luminance = (0.299 * BackgroundColor.Red + 0.587 * BackgroundColor.Green + 0.114 * BackgroundColor.Blue)/255
  
  If luminance > 0.5 Then
    c = 0 // bright colors - black font
  Else
    c = 255 // dark colors - white font
  End If
  
  Return  Color.RGB(c,c,c)
End Function

An Example:

Unbenannt

Gist: Find the contrasting color to a given color · GitHub

:slight_smile:

2 Likes

You can make the color calculation faster by using this code

Public Function ContrastColor(BackgroundColor As Color) As Color
  Var luminance As Integer = 0.299 * BackgroundColor.Red + 0.587 * BackgroundColor.Green + 0.114 * BackgroundColor.Blue
  If luminance > 127 Then
    Return  Color.Black
  Else
    Return  Color.White
  End If
End Function

Less calculation and no Color.RGB() call for the returned color.

3 Likes

yes, that’s right, thank you!

I give a solution and @TomE1 TomE tunes it for speed = TomE provides the solution. Now i’m sad :frowning:

No just joking. Glad i could help :slight_smile:

1 Like

really I took your solution sascha, the first given :slight_smile:

1 Like

Now @TomE1 may be sad :grinning: Because speed is really important when it comes to graphics, Tom‘s updated solution may be the „better“ one. :wink:

Thanks to TomE too !

1 Like

Perhaps there is even a better solution. Use inline if.
Here is my sample code from a button and a TextField “out” in a window.

#Pragma BackgroundTasks false

var d as double
const loopMax = 1000000
var c As Color = Color.Red
var result As Color

d = System.Microseconds
for i as integer = 1 to loopMax
  result = ContrastColor(Color.Red)
Next
d = (System.Microseconds - d) / 1000
out.AddText "ContrastColor: "+ str(d) + " ms" + EndOfLine

d = System.Microseconds
for i as integer = 1 to loopMax
  result = ContrastColorFast(c)
Next
d = (System.Microseconds - d) / 1000
out.AddText "ContrastColorFast: "+ str(d) + " ms" + EndOfLine

d = System.Microseconds
for i as integer = 1 to loopMax
  result = if(0.299 * c.Red + 0.587 * c.Green + 0.114 * c.Blue > 127, Color.Black, Color.White)
Next
d = (System.Microseconds - d) / 1000
out.AddText "ContrastColor inline: "+ str(d) + " ms" + EndOfLine

And this is the result:

ContrastColor: 765.8987 ms
ContrastColorFast: 595.8415 ms
ContrastColor inline: 97.60887 ms

I think it makes sense to use inline code within a paint event.

1 Like

From experience for stuff very like this, I should say ‘it depends’
If this occurs once in the paint event , it probably makes no difference.

But (as I found out from a change made to DynaPDFMBS) , even a tiny change to a function can make a big difference if repeated thousands of times.

HERE, my question is ‘how many different colors can there be to draw text over’?
Given the size of the screen and the size of words, I would be surprised if there were more than a few hundred.
(There are 216 web safe colors for example)

If that is the case, like many things that can be repeated a lot, pre-calculation is your friend.
Create a dictionary where each of the 216 colors is the key, and the value is the correct text color.
Then, getting the text color from the dictionary when it is needed will be faster than even the inline code if called thousands of times.

(In the test above, the inline code uses the same color and values in each pass. It may even be that the compiler optimised that method if it was smart enough)

I understand, Jeff, but in this app the user can choose any color, so the dictionary solution is not valid: but I retain the idea!

1 Like

Hi guys,
if you want to see a preview of black or white text on a given background color, check out https://www.0to255.com/
Greetings to all

If you’re a GraffitiSuite Desktop customer, I have this (Complement and ComplementReadable) and a bunch of other color functions in GraffitiColors.

2 Likes

Of course if you calculate it a million times. But I totally disagree if you need it for a few rects in a single paint loop.