Come posso determinare la variante di colore più scura o più chiara di un determinato colore?

StackOverflow https://stackoverflow.com/questions/97646

  •  01-07-2019
  •  | 
  •  

Domanda

Dato un colore sorgente di qualsiasi tonalità dal sistema o dall'utente, vorrei un semplice algoritmo che posso utilizzare per elaborare varianti più chiare o più scure del colore selezionato.Simile agli effetti utilizzati su Windows Live Messenger per definire lo stile dell'interfaccia utente.

Il linguaggio è C# con .net 3.5.

In risposta al commento: Il formato colore è (Alpha)RGB.Con valori come byte o float.

Risposta di valutazione: Per il contesto del mio utilizzo (alcuni semplici effetti dell'interfaccia utente), la risposta che contrassegno come accettata è in realtà la più semplice per questo contesto.Tuttavia, ho rinunciato ai voti anche per le risposte più complesse e accurate.Chiunque esegua operazioni di colore più avanzate e trovi questo thread in futuro dovrebbe assolutamente controllarli.Grazie SO.:)

È stato utile?

Soluzione

Moltiplica semplicemente i valori RGB per la quantità di cui desideri modificare il livello.Se uno dei colori è già al valore massimo, non puoi renderlo più luminoso (usando comunque la matematica HSV).

Ciò fornisce esattamente lo stesso risultato con molta meno matematica del passaggio a HSV e quindi della modifica di V.Ciò dà lo stesso risultato del passaggio a HSL e quindi della modifica di L, purché non si voglia iniziare a perdere la saturazione.

Altri suggerimenti

In XNA c'è il Color.Lerp metodo statico questo fa la differenza tra due colori.

Lerp è un'operazione matematica tra due float che modifica il valore del primo in base al rapporto della differenza tra loro.

Ecco un metodo di estensione per farlo su a float:

public static float Lerp( this float start, float end, float amount)
{
    float difference = end - start;
    float adjusted = difference * amount;
    return start + adjusted;
}

Quindi una semplice operazione lerp tra due colori utilizzando RGB sarebbe:

public static Color Lerp(this Color colour, Color to, float amount)
{
    // start colours as lerp-able floats
    float sr = colour.R, sg = colour.G, sb = colour.B;

    // end colours as lerp-able floats
    float er = to.R, eg = to.G, eb = to.B;

    // lerp the colours to get the difference
    byte r = (byte) sr.Lerp(er, amount),
         g = (byte) sg.Lerp(eg, amount),
         b = (byte) sb.Lerp(eb, amount);

    // return the new colour
    return Color.FromArgb(r, g, b);
}

Un esempio di applicazione di questo potrebbe essere qualcosa del tipo:

// make red 50% lighter:
Color.Red.Lerp( Color.White, 0.5f );

// make red 75% darker:
Color.Red.Lerp( Color.Black, 0.75f );

// make white 10% bluer:
Color.White.Lerp( Color.Blue, 0.1f );

HSV (Tonalità/Saturazione/Valore) chiamato anche HSL (Tonalità/Saturazione/Luminosità) è semplicemente una rappresentazione del colore diversa.

Utilizzando questa rappresentazione è più semplice regolare la luminosità.Quindi converti da RGB a HSV, schiarisci la "V", quindi riconverti in RGB.

Di seguito è riportato del codice C da convertire

void RGBToHSV(unsigned char cr, unsigned char cg, unsigned char cb,double *ph,double *ps,double *pv)
{
double r,g,b;
double max, min, delta;

/* convert RGB to [0,1] */

r = (double)cr/255.0f;
g = (double)cg/255.0f;
b = (double)cb/255.0f;

max = MAXx(r,(MAXx(g,b)));
min = MINx(r,(MINx(g,b)));

pv[0] = max;

/* Calculate saturation */

if (max != 0.0)
    ps[0] = (max-min)/max;
else
    ps[0] = 0.0; 

if (ps[0] == 0.0)
{
    ph[0] = 0.0f;   //UNDEFINED;
    return;
}
/* chromatic case: Saturation is not 0, so determine hue */
delta = max-min;

if (r==max)
{
    ph[0] = (g-b)/delta;
}
else if (g==max)
{
    ph[0] = 2.0 + (b-r)/delta;
}
else if (b==max)
{
    ph[0] = 4.0 + (r-g)/delta;
}
ph[0] = ph[0] * 60.0;
if (ph[0] < 0.0)
    ph[0] += 360.0;
}

void HSVToRGB(double h,double s,double v,unsigned char *pr,unsigned char *pg,unsigned char *pb)
{
int i;
double f, p, q, t;
double r,g,b;

if( s == 0 )
{
    // achromatic (grey)
    r = g = b = v;
}
else
{
    h /= 60;            // sector 0 to 5
    i = (int)floor( h );
    f = h - i;          // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    switch( i )
    {
    case 0:
        r = v;
        g = t;
        b = p;
    break;
    case 1:
        r = q;
        g = v;
        b = p;
    break;
    case 2:
        r = p;
        g = v;
        b = t;
    break;
    case 3:
        r = p;
        g = q;
        b = v;
    break;
    case 4:
        r = t;
        g = p;
        b = v;
    break;
    default:        // case 5:
        r = v;
        g = p;
        b = q;
    break;
    }
}
r*=255;
g*=255;
b*=255;

pr[0]=(unsigned char)r;
pg[0]=(unsigned char)g;
pb[0]=(unsigned char)b;
}

Il ricco Newmann discute il colore HSL rispetto a .NET System.Drawing.Color sul suo blog e anche fornisce una classe HSLColor questo fa tutto il lavoro per te.Converti il ​​tuo System.Drawing.Color in un HSLColor, aggiungi/sottrai valori rispetto alla Luminosità e riconverti in System.Drawing.Color per l'utilizzo nella tua app.

Puoi convertire il tuo colore nello spazio colore HSL, manipolarlo lì e riconvertirlo nel tuo spazio colore preferito (molto probabilmente è RGB)

I colori più chiari hanno un valore L più alto, quelli più scuri un valore L più basso.

Ecco le cose rilevanti e tutte le equazioni:

http://en.wikipedia.org/wiki/HSL_color_space

Un altro metodo è semplicemente interpolare il colore con il bianco o il nero.Questo desaturarà anche un po' il colore, ma è più economico da calcolare.

Ho utilizzato ControlPaint.Dark() e .Light() in System.Windows.Forms.

Immagino che tu stia utilizzando RGB con valori in byte (da 0 a 255) poiché è molto comune ovunque.

Per ottenere colori più luminosi, mediare i valori RGB con l'RGB del bianco.Oppure, per avere un certo controllo sulla quantità di schiarimento, mescolali in una certa proporzione.Permettere f variare da 0.0 a 1.0, quindi:

Rnew = (1-f)*R + f*255
Gnew = (1-f)*G + f*255
Bnew = (1-f)*B + f*255

Per colori più scuri, usa l'RGB del nero, che, essendo tutti zeri, semplifica i calcoli.

Tralascio dettagli come riconvertire il risultato in byte, cosa che probabilmente vorresti fare.

Se utilizzi i colori RGB, trasformerei i parametri di questo colore in HSL (tonalità, saturazione, luminosità), modificare il parametro luminosità e quindi trasformarlo nuovamente in RGB.Cerca su Google e troverai molti esempi di codice su come eseguire queste trasformazioni di rappresentazione del colore (da RGB a HSL e viceversa).

Questo è quello che ho trovato subito:http://bytes.com/forum/thread250450.html

Supponendo che tu ottenga il colore come RGB, convertilo prima nello spazio colore HSV (tonalità, saturazione, valore).Quindi aumentare/diminuire il valore per produrre una tonalità più chiara/più scura del colore.Quindi riconvertire in RGB.

Se i tuoi colori sono in formato RGB (o, presumibilmente CMYK), puoi utilizzare il metodo abbastanza rozzo per aumentare il valore di ciascun componente del colore.Ad esempio, in HTML i colori sono rappresentati come tre numeri esadecimali a due cifre.#ff0000 ti darà un rosso brillante, che può poi essere sbiadito aumentando i valori dei componenti G e B della stessa quantità, come #ff5555 (dà un rosso più chiaro).Presumibilmente per i colori Tonalità, Saturazione e Luminosità (HSL), puoi semplicemente aumentare la componente L, ma non posso dirlo con certezza;Ho meno familiarità con questo spazio colore.

Come ho detto, però, questo metodo è piuttosto rozzo.Dai miei ricordi di Live Messenger, sembra che tu stia cercando di creare gradienti, che possono essere applicati molto facilmente in Windows Presentation Foundation (WPF, parte di .NET 3.0).WPF supporta molti tipi diversi di pennelli sfumatura, inclusi gradienti lineari e radiali.

Posso consigliare vivamente il libro di Adam Nathan Windows Presentation Foundation scatenato come una buona e completa introduzione a WPF.

HTH

Eventuali variazioni di colore sono meglio eseguite in HSL/HSV.

Un buon test consiste nell'interpolare tra due valori equivalenti nello spazio RGB e nello spazio HSL.La rampa nello spazio HSL sembra una progressione naturale.Nello spazio RGB in genere appare piuttosto innaturale.L'HSL si adatta alla nostra percezione visiva dello spazio colore molto meglio dell'RGB.

L'idea di convertire in HSV o in qualche altro spazio colore sembra buona e potrebbe essere necessaria per un lavoro cromatico preciso, ma per scopi ordinari l'errore di lavorare in RGB potrebbe non essere sufficiente.Inoltre, può essere una seccatura affrontare casi limite:RGB è uno spazio a forma di cubo, mentre HSV no.Se si lavora con valori byte, è possibile avere mappature molti-a-uno e uno-a-molti tra gli spazi.Questo potrebbe rappresentare o meno un problema a seconda dell'applicazione.YMMV

Questo sito web rileva che è possibile utilizzare la classe ControlPaint all'interno dello spazio dei nomi BCL C# System.Windows.Forms.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top