2011-07-20 22 views
13

No sé mucho sobre la composición del color, así que se me ocurrió este algoritmo que seleccionará un color de fondo basado en el color de la fuente en una prueba y errores base:Cómo elegir un color de fondo según el color de la fuente para tener el contraste adecuado

public class BackgroundFromForegroundColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (!(value is Color)) 
      return value; 
     Color color = (Color)value; 
     if (color.R + color.G + color.B > 550) 
      return new SolidColorBrush(Colors.Gray); 
     else if (color.R + color.G + color.B > 400) 
      return new SolidColorBrush(Colors.LightGray); 
     else 
      return new SolidColorBrush(Colors.White); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

me hizo un poco de google sobre esto, pero no he encontrado nada muy formal acerca de las diferentes formas en que un color de fondo se puede calcular para obtener un buen efecto de contraste con el color de la fuente.

Así que mi pregunta es: ¿hay un enfoque más "formal" para elegir un buen fondo para obtener un buen contraste? Alternativamente, ¿cómo manejarías elegir un color de fondo con la única intención de que tu texto sea lo más legible posible sin importar el color de la fuente?

rápida actualización

Un poco más de contexto: Estoy simplemente tratando de mostrar una vista previa de un texto (por ejemplo, "El rápido zorro marrón salta sobre el perro perezoso") donde el usuario elige el color de la fuente , peso, fuente, etc. Sin embargo, estoy interesado en ver qué se puede hacer, ya sea súper simple o más complejo.

edición final

decidí a ir con lo que sugirió H.B.: parece que funciona bien con todos los colores que probé a diferencia de mi anterior algoritmo fueron el primer plano no siempre adecuadamente contrastaría con el fondo. Hubiera tenido curiosidad de ver si hay una fórmula que te brinde un fondo "óptimo" para un primer plano dado, pero para lo que necesito en blanco y negro funciona bien. Este es mi código en su forma actual:

public class BackgroundFromForegroundColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (!(value is Color)) 
      return value; 
     Color color = (Color)value; 
     double Y = 0.2126 * color.ScR + 0.7152 * color.ScG + 0.0722 * color.ScB; 
     return Y > 0.4 ? Brushes.Black : Brushes.White; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 
+1

Motivo similar cubierto aquí: [Hacer foregroundcolor en negro o blanco dependiendo del fondo] (http://stackoverflow.com/questions/2241447/make-foregroundcolor-black-or-white-depending-on-background), [Bueno color de primer plano de texto para un color de fondo dado] (http://stackoverflow.com/questions/946544/good-text-foreground-color-for-a-given-background-color) y [¿Cuáles son sus métodos de extensión favoritos para C# ?] (http://stackoverflow.com/questions/271398/what-are-your-favorite-extension-methods-for-c-codeplex-com-extensionoverflow/6031710#6031710) – takrl

+0

Como nota al margen, el 'ConvertBack 'en una forma, los convertidores deberían lanzar una' NotSupportedException' ya que no habrá implementación. –

Respuesta

15

Existen algunos métodos para calcular el brillo de un color, basándose en que podría tomar un fondo negro o blanco y obtendría una legibilidad decente. Consulte luma por ejemplo

Y = 0.2126 R + 0.7152 G + 0.0722 B

creo que el umbral sería 0,5 si utiliza valores de entrada normalizadas (0.0 - 1.0), pero ha sido un tiempo desde que he utilizado esta ...

Editar: Ejemplo convertir aplicación boceto:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
{ 
    var c = (Color)value; 
    var l = 0.2126 * c.ScR + 0.7152 * c.ScG + 0.0722 * c.ScB; 

    return l < 0.5 ? Brushes.White : Brushes.Black; 
} 

el umbral puede ser en realidad un poco dependiente de la pantalla y las preferencias personales, por mi parte, preferiría algo más bajo que resulta en una mayor participación en fondos negros.

+0

Elegir blanco o negro parece que funcionaría; ahora usando la fórmula de luma como la publicaste, Y variará entre 0 y 255; ¿Alguna idea sobre dónde dibujaría la línea en la arena? –

+0

Creo que entiendo lo que quiere decir con 0.5: 0.5 * 255 = 127.5; if> luego use fondo negro; de lo contrario, use blanco. AFAICT con una serie de colores aleatorios, parece funcionar muy bien! –

+0

Esa es una forma de verlo (también podría dividir todos los canales por 255.0, o el resultado); funciona, es por eso que lo usé antes (hace dos años). –

3

Creo que esto es más que un problema de diseño que tener una forma 'formal'. Por lo tanto, es un poco a tu propia decisión. ¿Puedes mostrar algunos ejemplos cercanos a lo que estás tratando de lograr? También estoy trabajando en algo similar a su problema en estos días (creando una galería en línea que cambia su BG de acuerdo con los colores de las fotos en la galería de forma dinámica), y creo que estoy yendo bastante bien, mi consejo es que, sea lo que sea, elija como fondo, simplemente cree una capa de negro o blanco en el fondo, dependiendo de su color de primer plano (brillo opuesto), y de esa manera está, en cierto sentido, "limitando" el BG, por ejemplo BG se puede configurar en negro, y el texto también es negro, pero hay una capa blanca encima de BG que hace que el texto sea legible. La opacidad de la capa le queda, intente y vea cuál es el mejor valor. Y puede implementar todo en el convertidor de valor, y esa composición BG + 'capa' no es más que un valor de color.

1

En un proyecto en el que trabajo decidimos una fórmula que separa el color de los valores de Red Green Blue y restamos Red Green y Blue de 255 para obtener un color de contraste casi perfecto.

Sin embargo ... Gris es uno de esos colores que no funcionaría con esta fórmula. Puede verificar simplemente si el color es gris antes de restar. Hay otros colores en ambos extremos del espectro de color en los que es posible que tenga que sostener su mano para obtener un color de contraste legible.

+0

No creo que sea visualmente atractivo, como rojo sobre cian o verde sobre magenta no sería muy agradable de ver, IMO. Pero por lo demás es bueno crear contraste de todos modos, a menos que el color sea casi gris, por supuesto. –

+0

@can poyrazoğlu - El autor pidió un buen método para encontrar el contraste, el color en el otro extremo del espectro daría exactamente eso. El color de contraste para Rojo con este método es realmente muy bueno. Verde amarillo; Olvidé de qué color es exactamente. –

3

La supresión de Ramhound falla por completo para los colores que tienen cada componente cerca del valor 128 (no todo gris, como se sugiere) - ¡entonces se obtiene casi el mismo color!

El (diferente) de color más contrastante para cualquier color dado c sólo tiene que llegar por

new Color(c.R > .5 ? 0 : 1, c.G > .5 ? 0 : 1, c.B > .5 ? 0 : 1) 

o si necesita 0-255 gama

new Color(c.R > 127 ? 0 : 255, c.G > 127 ? 0 : 255, c.B > 127 ? 0 : 255) 

Esa visibilidad del texto en el fondo siempre se encuentra dada lo mejor, pero no siempre agradable. En caso de que no quieras molestar por colores locos, solo terminas usando negro/blanco sugerido por la respuesta aceptada.

Cuestiones relacionadas