2009-07-22 9 views
28

So che questo non invertirà direttamente un colore, lo "opporrà" semplicemente. Mi stavo chiedendo se qualcuno conoscesse un modo semplice (poche righe di codice) per invertire un colore da un dato colore?Come si inverte un colore/colore?

Al momento ho questo (che non è esattamente la definizione di un invertito, perché se mi passa un colore grigio/grigio tornerà qualcosa ad esempio 127, 127, 127 estremamente simili):

const int RGBMAX = 255; 

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

In realtà, questo * è * il modo in cui viene in genere definito l'inversione di un colore ... cosa stai cercando invece? –

+0

E se il mio colore fosse 127, 127, 127, passando per la mia funzione non lo invertirai .. – ThePower

+1

Forse hai bisogno di generare un colore di sfondo su cui il tuo colore sarà leggibile? –

risposta

41

Dipende da cosa si intende per "invertire" un colore

Il codice fornisce un colore "negativo".

Stai cercando trasformare rosso in ciano, verde in viola, blu in giallo (e così via)? In tal caso, devi convertire il tuo colore RGB nella modalità HSV (troverai here per effettuare la trasformazione).

Quindi è sufficiente invertire il valore di tonalità (modificare Hue da 360-Hue) e riconvertire in modalità RGB.

EDIT: come ha detto Alex Semeniuk, cambiando Hue da (Hue + 180) % 360 è una soluzione migliore (non invertire il Hue, ma trovare il colore opposto sul cerchio di colore)

+0

sì, finalmente una risposta significativa. +1 – jalf

+1

+1 per rispondere effettivamente alla mia domanda con la soluzione corretta (piuttosto che fornire un'alternativa al codice che ho postato) – ThePower

+0

Mescolare questo combinato con http://stackoverflow.com/questions/2942/hsl-in-net/2504318 # 2504318 è esattamente quello che sono andato con. Grazie! – Yoopergeek

10

Prova questo:

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

è fatto allo stesso modo in C#. La sintassi è esattamente la stessa. 0xFFFFFFFF^color –

+0

Quasi identico. :) Ho appena apportato le modifiche minori per trasformarlo in C#. – Noldorin

+3

È lo stesso del codice nella domanda – Eyal

4

invertire i bit di ogni componente separatamente:

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

EDIT: l'operatore ~ ​​non funziona automaticamente con i byte, è necessario il cast.

+0

Questo genera un'eccezione (ArgumentException "Valore di '-129' non valido per 'rosso'") – ThePower

+0

Sì, mancava quello, risposta corretta. –

+0

Ora è stato modificato, è meglio, anche se fa sempre lo stesso della mia funzione rispetto all'essere un negativo, non un invertito. grazie comunque per la risposta :-) – ThePower

4

quello che hai già è un RGB- Invertire. Esistono altri modi per classificare i colori e quindi altre definizioni per Inverse of a Color.

Ma sembra che tu voglia un colore contrastante, e non c'è una semplice inversione che funzionerà per tutti i colori incluso RGB (127, 127, 127).

Quello che vi serve è 1) una conversione per HSV (vedi ThibThibs risposta) e invertire la tonalità, ma anche 2) controllare se la tonalità non è troppo vicino al centro e, se in modo da andare a uno completamente brillante o completamente buio.

+1

Il teorema del punto fisso implica che qualsiasi funzione continua da (a valore reale) da Colore a Colore lascerà un valore invariato, se la funzione è ragionevolmente uniforme, allora una patch attorno a quel punto non si muoverà molto, quindi –

14

È possibile utilizzare:

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

Sarà invertire MyColor.

+6

127, 127, 127? – ThePower

+1

Dà un grigio leggermente più chiaro: 128, 128, 128 – Jerther

+1

Penso che questa sia una buona risposta in molti casi, ad esempio il rosso verrà convertito in ciano. è l'equivalente vbnet del codice di Remy: 'MyColor = Color.FromArgb (MyColor.ToArgb() Xor & Hffffff)' – Alex

3

Se si desidera cambiare ogni colore, provare una funzione di rotazione (spostamento o aggiunta) piuttosto che una funzione di inversione (invertendo). In altre parole, considera l'intervallo da 0 a 255 per ogni singolo colore (rosso, verde e blu) da avvolgere, collegato alle punte come un cerchio di valori. Quindi sposta ciascun colore attorno al cerchio aggiungendo un valore e facendo mod 256. Ad esempio, se il tuo valore iniziale per il rosso è 255 e aggiungi 1, ottieni 0. Se sposti tutti e tre i colori per 128, diventi drammaticamente diverso valori per ogni colore originale nell'immagine, anche i grigi. Grigio 127, 127, 127 diventa bianco 255, 255, 255. Grigio 128, 128, 128 diventa nero 0, 0, 0. C'è un effetto fotografico come quello chiamato Solarizzazione, scoperto per caso da Man Ray negli anni '30.

È inoltre possibile eseguire operazioni di rotazione su ciascun colore (rosso, verde, blu) di una quantità diversa per incasinare realmente un'immagine.

È anche possibile fare operazioni di rotazione di Hue, spostando la tonalità di ogni colore originale di una certa quantità sul cerchio tonalità, che altera tutti i colori senza alterare la luminosità, in modo che le ombre guardano ancora come ombre, rendendo le persone assomigliare Simpson o Smurphs per esempio.

Il codice per uno spostamento di 128 potrebbe sembrare:

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

Il modo più semplice e pigro fatta funzionare con avere non solo triplo 12x, ma valori misti, è questo:

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); 
} 

Ora, invertedColor ha un colore diverso rispetto all'originale, anche se abbiamo un valore di colore 128, 128, 128 o vicino ad esso.