Respondi a uma pergunta semelhante no Game Development Stack Exchange há um tempo, então deixe-me resumir as respostas lá.
Sua idéia de escolher preto ou branco, dependendo de qual contrasta melhor com a cor do plano de fundo, é sólida. No entanto, calcular a média dos componentes RGB não dará uma boa indicação de como uma determinada cor aparecerá clara no olho humano, por (principalmente) duas razões:
Antes de tudo, por razões relacionadas à percepção humana da cor, os canais vermelho, verde e azul não possuem a mesma luminância relativa ; de fato, o azul puro ( #0000ff
) é apenas 10% mais brilhante (e o vermelho puro apenas 30% mais brilhante) do que o verde puro ( #00ff00
). Assim, por exemplo, texto preto em azul puro nunca terá um contraste particularmente bom.
Por exemplo, as imagens abaixo mostram exemplos de texto em preto e branco em fundo vermelho, verde e azul puro ( #ff0000
, #00ff00
e #0000ff
):
Você pode ver claramente as diferenças em contraste, mesmo que todas essas cores tenham o mesmo valor médio de RGB.
A outra complicação é que os espaços de cores RGB normalmente usados em telas de computador (como sRGB ) não são lineares, mas têm uma gama de exibição em torno de 2 ou mais. Isso significa que, por exemplo, a cor RGB #7f7f7f
= "50% cinza" na verdade não aparece metade do brilho do branco puro ( #ffffff
), mas apenas cerca de 25% do brilho, enquanto a cor que realmente possui uma luminosidade relativa no meio caminho entre preto e branco é realmente mais perto de "75% cinza" ( #bfbfbf
).
Convenientemente, porém, o olho humano também não é linear e é mais sensível às diferenças em tons mais escuros. De fato, para tons de cinza, as não linearidades se cancelam aproximadamente, de modo que o RGB 50% de cinza ( #7f7f7f
) ainda está perceptivamente igualmente distante do preto e do branco. Como demonstração, veja alguns textos em preto e branco em fundos de 25%, 50% e 75% de cinza ( #3f3f3f
, #7f7f7f
e #bfbfbf
):
No entanto, para calcular com precisão a luminosidade de uma cor RGB arbitrária, precisamos levar em consideração a gama da tela, pois são os valores de luminosidade linear que precisam ser medidos.
Para juntar tudo, para determinar se o texto em preto ou branco teria melhor contraste em um plano de fundo, é necessário:
- converta os valores de cores RGB compactados em gama em RGB linear,
- tomar uma média ponderada dos componentes lineares R, G e B e
- compare a média resultante com um limite adequado.
O valor do limiar que fornece melhores resultados pode ser determinado experimentalmente, mas geralmente se espera que fique próximo da luminância de 50% de cinza RGB. De qualquer forma, vale a pena notar que o contraste percebido varia de acordo com as configurações de exibição e as condições de exibição do monitor, portanto, não existe um valor ideal para todos, mas uma gama bastante ampla de opções mais ou menos igualmente boas.
Se você deseja apenas uma fórmula simples para conectar números, tente o seguinte:
- se 0,2126 × R γ + 0,7152 × G γ + 0,0722 × B γ > 0,5 γ , escolha preto; mais escolha branco,
onde γ é o valor gama aproximado da exibição ( γ = 2,2 é típico).
Para uma aproximação ainda mais simples, você pode ignorar a correção gama (ou seja, assumir efetivamente que γ = 1) e apenas usar a condição 0,2126 × R + 0,7152 × G + 0,0722 × B > 0,5. Para tons de cinza, isso não fará diferença (já que estamos aplicando a mesma gama nos dois lados da desigualdade), mas superestima um pouco a luminância das cores saturadas. Felizmente, nessas cores, preto e branco tendem a ter um contraste decente de qualquer maneira; portanto, o erro pode não ter muita importância na prática.
Por fim, observe que, se a cor do plano de fundo não for uniforme, é possível que nenhuma cor de texto única pareça boa. Nesses casos, você pode considerar, por exemplo, o uso de texto em preto com um contorno branco, ou vice-versa, ou talvez cercar o texto com uma caixa semitransparente da cor oposta.