.NET Fehler: Color-Klasse HSB/HSL

Erstellt am 29.07.08 von Markus, keine Kommentare, Tags: Informatik,

Bei Verwendung der C#-Color-Klasse ist mir ein Fehler aufgefallen. Die Werte der HSB-Methoden stimmen nicht. Oder anders gesagt, sie liefern nicht die Werte, die man erwartet. Bei den gegebenen Methodennamen denkt man sofort ans HSB/HSV-Modell. Die Werte, die zurückgegeben werden, entsprechen jedoch dem HSL-Modell, das den Sättigungswert anders berechnet und einen Lightness-Wert besitzt, der ebenfalls anders berechnet wird als der Brightnesswert.

getHue()
getSaturation()
getBrightness()

HSB nimmt bei der Helligkeit beispielsweise einfach das Maximum der RGB-Werte, während HSL den Mittelwert zwischen Minimum und Maximum benutzt. Bei der Sättigung gibt es auch Unterschiede. Ursache hierfür ist die andere geometrische Grundlage: Während HSB als Kegel visualisiert wird, ist HSL ein Doppelkegel. Hierdurch liegt die maximale HSL-Sättigung bei einem L von 50%; bei HSB muss L=0 sein. Somit kann man bei HSL ausschließlich durch das L schwarz und weiß erzeugen (L=100% weiß); beim HSB-Modell muss zusätzlich noch die Sättigung auf 0 reduziert werden.

Eine gute Visualisierung und die Formeln gibts hier. Mit diesem Wissen, kann die Color-Klasse leicht an das HSB-Modell angepasst werden bzw. eine eigene erstellt werden. Nachfolgend der Konstruktor einer solchen Klasse (H [0..360]; S,V [0..100]):

public ColorHSV(byte r, byte g, byte b)
{
float red, green, blue;
red = r / 255.0f;
green = g / 255.0f;
blue = b / 255.0f;

//RGB -> HSV
float min = Math.Min(Math.Min(red, green), blue);
float max = Math.Max(Math.Max(red, green), blue);

//H
if ((red == green) && (green == blue))
{
h = 0;
}
else
{
if (max == red) h = 60 * ((green - blue) / (max - min));
else if (max == green) h = 60 * (2 + ((blue - red) / (max - min)));
else if (max == blue) h = 60 * (4 + ((red - green) / (max - min)));

if (h < 0) h += 360;
h = (float)Math.Round(h);
}

//S
if (max == 0)
{
s = 0;
}
else
{
s = (float)Math.Round(100 * ((max - min) / max));
}

//V
v = (float)Math.Round(100 * max);
}

Kommentare

Noch keine Kommentare.

Kommentar erstellen