2009-07-22 24 views
28

Sé que esto no invertirá directamente un color, simplemente lo "opondrá". Me preguntaba si alguien sabía de una manera simple (unas líneas de código) para invertir un color de cualquier color dado?¿Cómo invierto un color/color?

Por el momento tengo esto (que no es exactamente la definición de un invertido, ya que si lo paso un color gris/gris se volverá algo por ejemplo, 127, 127, 127 muy similar):

const int RGBMAX = 255; 

Color InvertMeAColour(Color ColourToInvert) 
{ 
    return Color.FromArgb(RGBMAX - ColourToInvert.R, 
     RGBMAX - ColourToInvert.G, RGBMAX - ColourToInvert.B); 
} 
+8

En realidad, esa * es * la forma en que se suele definir la inversión de un color ... ¿qué estás buscando en su lugar? –

+0

¿Qué pasa si mi color es 127, 127, 127, pasando por mi función no lo invertiría .. – ThePower

+1

Tal vez necesita generar un color de fondo que sea legible en su color? –

Respuesta

41

Depende de lo qué se refiere con "invertir" un color

Su código proporciona un color "negativo".

¿Está buscando transformar rojo en cian, verde en morado, azul en amarillo (y así sucesivamente)? Si es así, debe convertir su color RGB en el modo HSV (encontrará here para realizar la transformación).

Luego solo necesita invertir el valor del tono (cambie Hue por 360-Hue) y vuelva a convertirlo al modo RGB.

EDIT: como Alex Semeniuk ha mencionado, el cambio de Hue por (Hue + 180) % 360 es una mejor solución (que no invierte la tonalidad, pero encontrar el color opuesto en el círculo de color)

+0

yup, finalmente una respuesta significativa. +1 – jalf

+1

+1 por responder mi pregunta con la solución correcta (en lugar de proporcionar una alternativa al código que publiqué) – ThePower

+0

Mezclar esto combinado con http://stackoverflow.com/questions/2942/hsl-in-net/2504318 # 2504318 es exactamente lo que fui. ¡Gracias! – Yoopergeek

10

Prueba esto:

uint InvertColor(uint rgbaColor) 
{ 
    return 0xFFFFFF00u^rgbaColor; // Assumes alpha is in the rightmost byte, change as needed 
} 
+0

se hace de la misma manera en C#. La sintaxis es exactamente la misma. 0xFFFFFFFF^color –

+0

Casi idéntico. :) Acabo de hacer los cambios menores para convertirlo en C#. – Noldorin

+3

Esto es lo mismo que el código en la pregunta – Eyal

4

invertir los bits de cada componente por separado:

Color InvertMeAColour(Color ColourToInvert) 
{ 
    return Color.FromArgb((byte)~ColourToInvert.R, (byte)~ColourToInvert.G, (byte)~ColourToInvert.B); 
} 

EDITAR: El operador ~ no trabaja con bytes automáticamente, se necesita conversión.

+0

Esto arroja una excepción (ArgumentException "Valor de '-129' no es válido para 'rojo'") – ThePower

+0

Sí, perdí esa respuesta corregida. –

+0

Ahora ha sido editado eso es mejor, aunque todavía hace lo mismo que mi función con respecto a ser negativo, no invertido. gracias por la respuesta de todos modos :-) – ThePower

4

lo que ya tiene es un RGB- Invertir. Hay otras formas de clasificar los colores y, por lo tanto, otras definiciones para el inverso de un color.

Pero parece que quizás desee un Color de contraste, y no hay una Inversión simple que funcione para todos los colores, incluido RGB (127, 127, 127).

Lo que necesita es 1) una conversión a HSV (consulte la respuesta de ThibThibs) e invierta el tono, pero también 2) compruebe si el tono no es demasiado cercano al medio y, de ser así, vaya a totalmente brillante o completamente oscuro.

+1

El teorema del punto fijo implica que cualquier función continua desde (real-valued) Color to Color dejará sin cambios un valor: si la función es razonablemente suave, entonces un parche alrededor de ese punto tampoco se moverá mucho, –

14

Se puede utilizar:

MyColor=Color.FromArgb(MyColor.ToArgb()^0xffffff); 

Se invertirán MyColor.

+6

¿Qué significa eso para el gris? 127, 127, 127? – ThePower

+1

Da un gris ligeramente más claro: 128, 128, 128 – Jerther

+1

Creo que esta es una muy buena respuesta para muchos casos. Por ejemplo, el rojo se convertirá en cian. es el equivalente de vbnet del código de Remy: 'MyColor = Color.FromArgb (MyColor.ToArgb() Xor & Hffffff)' – Alex

3

Si desea cambiar todos los colores, intente con una función de rotación (desplazamiento o adición) en lugar de una función de inversión (inversión). En otras palabras, considere que el rango de 0 a 255 para cada color (rojo, verde y azul) debe envolverse, conectado en las puntas como un círculo de valores. Luego cambie cada color alrededor del círculo agregando algún valor y haciendo el mod 256. Por ejemplo, si su valor inicial para rojo es 255 y agrega 1, obtiene 0. Si cambia los tres colores por 128, se vuelve dramáticamente diferente valores para cada color original en la imagen, incluso los grises. Gris 127, 127, 127 se vuelve blanco 255, 255, 255. Gris 128, 128, 128 se vuelve negro 0, 0, 0. Hay un efecto fotográfico como el llamado Solarización, descubierto por casualidad por Man Ray en la década de 1930.

También puede realizar operaciones de rotación en cada color (rojo, verde, azul) en una cantidad diferente para realmente estropear una imagen.

También puede realizar operaciones de rotación en el tono, cambiando el tono de cada color original en cierta cantidad en el círculo de tono, que altera todos los colores sin alterar el brillo, por lo que las sombras se ven como sombras, haciendo que las personas se vean Simpsons o Smurphs por ejemplo.

El código para un cambio en un 128 podría parecer:

public static Color Invert(this Color c) => Color.FromArgb(c.R.Invert(), c.G.Invert(), c.B.Invert()); 

public static byte Invert(this byte b) { 
    unchecked { 
     return (byte)(b + 128); 
    } 
} 
1

La forma más sencilla y perezoso me hizo trabajar con tener no sólo el triple de 12x, pero los valores mixtos, es la siguiente:

Color invertedColor= Color.FromArgb(fromColor.ToArgb()^0xffffff); 

if (invertedColor.R > 110 && invertedColor.R < 150 && 
    invertedColor.G > 110 && invertedColor.G < 150 && 
    invertedColor.B > 110 && invertedColor.B < 150) 
{ 
    int avg = (invertedColor.R + invertedColor.G + invertedColor.B)/3; 
    avg = avg > 128 ? 200 : 60; 
    invertedColor= Color.FromArgb(avg, avg, avg); 
} 

Ahora, invertedColor tiene un color diferente que el original, incluso si tenemos un valor de color de 128, 128, 128 o cerca de él.

Cuestiones relacionadas