I'm writing a program for fun which generates random colours for text. (If you're curious: https://github.com/Arunscape/acat)

So, I have 3 variables $r, g$, and $b$ , each of which can be any integer $\in [0, 256)$

I figure that if I want dark text on a light background, or light text on a dark background, I should generate $r,g,b$ such that their sum is within a range, either

$r + g + b \leq 255 \quad r,g,b \in [0, 255]$ for dark text


$r + g + b \geq 255 \quad r,g,b \in [0, 255]$ for light text

Here is my thought process so far for approaches I could take:

  1. generate $r$, let's say we get $r=100$
  2. g = random_num_in_range($0, 256-r)$, let's say we get $g=100$
  3. b = random_num_in_range(0, 256-r-g), let's say we get $b=50$

In this example, I would get a dark-ish yellow colour for use with a light background However, because r is always the first number to be generated, would this algorithm have some sort of bias, or would the generated colours be random?

If this algorithm does work, can I make it more efficient? I will be generating lots of colours, so the less CPU cycles I can waste, the better.

Another approach I'm thinking I could take is, instead of generating 3 random numbers for each colour, is it possible to say, generate a number between 0 and $256^3 - 1$ and then map the number to r,g,b values. (or rather I would generate numbers in the range, $[0,0x7FFFFF]$ for dark values and $[0x800000, 0xFFFFFF]$ for lighter values.

Now that I think of it, that's kind of close to hex colour codes, except that for hex colour codes, the 2 leftmost digits are r, the 2 middle are g, and the 2 left ones are for b

Or, is there some other approach that I completely missed that's much better than what I came up with? 😄

  • $\begingroup$ Just randomize also the order of variables when choosing the random numbers to get rid of the bias. $\endgroup$ – trancelocation Jul 16 '20 at 3:07

Your approach will definitely bias $r$ high-it will average $127.5$ and $b$ low. A simple approach is to generate four numbers, $r,g,b$ in a fixed range and a sum to normalize to. Multiply each one by $\frac {desired sum}{actual sum}$ and you are there. Certainly you can generate one random number and split it into four bytes, however the low order bits of a random number are often much less random than the high order bits.

I would be surprised if a simple sum of $r+g+b$ got you a good split of light vs. dark colors. Note that $255$ is $\frac 13$ of the way up, not $\frac 12$.

  • $\begingroup$ just making sure I understand-- so you're saying generate 4 numbers, say r,g,b, x then multiply each by x/(r+g+b) ? $\endgroup$ – Arunscape Jul 16 '20 at 3:01
  • $\begingroup$ Yes, that is correct. $\endgroup$ – Ross Millikan Jul 16 '20 at 3:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.