2009-08-26 16 views

risposta

17

Non penso che ci sia un metodo per farlo nel framework .NET.
Partenza Converting HSV to RGB colour using C#

Questo è il codice di implementazione,

void HsvToRgb(double h, double S, double V, out int r, out int g, out int b) 
{  
    double H = h; 
    while (H < 0) { H += 360; }; 
    while (H >= 360) { H -= 360; }; 
    double R, G, B; 
    if (V <= 0) 
    { R = G = B = 0; } 
    else if (S <= 0) 
    { 
    R = G = B = V; 
    } 
    else 
    { 
    double hf = H/60.0; 
    int i = (int)Math.Floor(hf); 
    double f = hf - i; 
    double pv = V * (1 - S); 
    double qv = V * (1 - S * f); 
    double tv = V * (1 - S * (1 - f)); 
    switch (i) 
    { 

     // Red is the dominant color 

     case 0: 
     R = V; 
     G = tv; 
     B = pv; 
     break; 

     // Green is the dominant color 

     case 1: 
     R = qv; 
     G = V; 
     B = pv; 
     break; 
     case 2: 
     R = pv; 
     G = V; 
     B = tv; 
     break; 

     // Blue is the dominant color 

     case 3: 
     R = pv; 
     G = qv; 
     B = V; 
     break; 
     case 4: 
     R = tv; 
     G = pv; 
     B = V; 
     break; 

     // Red is the dominant color 

     case 5: 
     R = V; 
     G = pv; 
     B = qv; 
     break; 

     // Just in case we overshoot on our math by a little, we put these here. Since its a switch it won't slow us down at all to put these here. 

     case 6: 
     R = V; 
     G = tv; 
     B = pv; 
     break; 
     case -1: 
     R = V; 
     G = pv; 
     B = qv; 
     break; 

     // The color is not defined, we should throw an error. 

     default: 
     //LFATAL("i Value error in Pixel conversion, Value is %d", i); 
     R = G = B = V; // Just pretend its black/white 
     break; 
    } 
    } 
    r = Clamp((int)(R * 255.0)); 
    g = Clamp((int)(G * 255.0)); 
    b = Clamp((int)(B * 255.0)); 
} 

/// <summary> 
/// Clamp a value to 0-255 
/// </summary> 
int Clamp(int i) 
{ 
    if (i < 0) return 0; 
    if (i > 255) return 255; 
    return i; 
} 
+6

Grazie per questo metodo. Strano che Color abbia .GetHue(), .GetSaturation() e .GetBrightness(), ma nessun metodo inverso come .fromHSB(). – MusiGenesis

+0

In effetti ... è un'omissione molto strana, imo. – jsight

+0

Perché non restituire un oggetto Color invece di utilizzare * out * per tre valori separati? –

48

Non c'è un metodo incorporato per fare questo, ma i calcoli non sono terribilmente complessa.
Nota inoltre che Color's GetHue(), GetSaturation() e GetBrightness() restituiscono valori HSL, non HSV.

Il seguente codice C# converte tra RGB e HSV utilizzando gli algoritmi descritti in Wikipedia.
Ho già postato questa risposta here, ma copierò il codice qui per una rapida consultazione.

public static void ColorToHSV(Color color, out double hue, out double saturation, out double value) 
{ 
    int max = Math.Max(color.R, Math.Max(color.G, color.B)); 
    int min = Math.Min(color.R, Math.Min(color.G, color.B)); 

    hue = color.GetHue(); 
    saturation = (max == 0) ? 0 : 1d - (1d * min/max); 
    value = max/255d; 
} 

public static Color ColorFromHSV(double hue, double saturation, double value) 
{ 
    int hi = Convert.ToInt32(Math.Floor(hue/60)) % 6; 
    double f = hue/60 - Math.Floor(hue/60); 

    value = value * 255; 
    int v = Convert.ToInt32(value); 
    int p = Convert.ToInt32(value * (1 - saturation)); 
    int q = Convert.ToInt32(value * (1 - f * saturation)); 
    int t = Convert.ToInt32(value * (1 - (1 - f) * saturation)); 

    if (hi == 0) 
     return Color.FromArgb(255, v, t, p); 
    else if (hi == 1) 
     return Color.FromArgb(255, q, v, p); 
    else if (hi == 2) 
     return Color.FromArgb(255, p, v, t); 
    else if (hi == 3) 
     return Color.FromArgb(255, p, q, v); 
    else if (hi == 4) 
     return Color.FromArgb(255, t, p, v); 
    else 
     return Color.FromArgb(255, v, p, q); 
} 
+0

Il tuo ColorFromHSV potrebbe avere qualcosa di sbagliato con esso, stavo cercando di ruotare la tonalità di 180 gradi utilizzando il codice per un colore opposto e non sta funzionando troppo bene. Il codice accettato dà un colore diverso che mi sembra corretto. –

+0

Sto usando la tua funzione ColorToHSV, comunque. Sembra che funzioni bene. –

+0

@IsaacBolinger non funziona bene con la tonalità negativa, funziona bene per la tonalità> = 0, ma meglio usare la tonalità tra <0, 360) nel codice. – xmedeko

-1

Guarda http://richnewman.wordpress.com/hslcolor-class/ che ha un eccellente classe C# per fornire tutte le conversioni necessarie, comprese da e per i colori di sistema di Windows.

+0

La domanda è per HSB/V, non HSL, che viene spesso mescolata. In effetti, la stessa Microsoft ha ottenuto in modo errato facendo riferimento a Color.GetBrightness() per essere HSB, dove in realtà è HSL. – redshift5

12

Non è integrato, ma esiste una libreria C# open source denominata ColorMine che semplifica la conversione tra gli spazi colore.

Rgb HSV:

var rgb = new Rgb {R = 123, G = 11, B = 7}; 
var hsv = rgb.To<Hsv>(); 

HSV a RGB:

var hsv = new Hsv { H = 360, S = .5, L = .17 } 
var rgb = hsv.to<Rgb>();