Umrechnung HSV nach RGB

Hallo,

ich arbeite derzeit noch an meiner WS2812-Lib in avr-gcc.

Jedoch habe ich gerade keine Ahnung, wie ich die HSV nach RGB Umrechung richtig darstellen kann.
Wie kann ich es anstellen, dass ich keine großen Unterschiede in der Helligkeit bekomme?

Was ich genau damit meine, wenn 2 Farbwerte ~MAX sind, ist das deutlich heller, als wenn 1 Farbwert MAX ist.

void hsv(uint16_t hue, uint8_t saturation, uint8_t value, uint8_t *red, uint8_t *green, uint8_t *blue)
{
	/*
	hue             (Farbton) :   0 ... 359 °
	saturation  (Saettingung) :   0 ... 100 %
	value          (Hellwert) :   0 ... 100 %
	
	*/
	
	if(hue == 360)		hue = 0;
	else if(hue > 360)	return;
	
	switch((hue)/60)
	{
		case 0: //   0 -  59
		*red	= 255;
		*green	= (425 * hue) / 100;
		*blue	= 0;
		break;
		
		case 1: //   60 - 119
		*red	= 255 - (425 * (hue - 60)) / 100;
		*green	= 255;
		*blue	= 0;
		break;
		
		case 2: //  120 - 179
		*red	= 0;
		*green	= 255;
		*blue	= (425 * (hue - 120)) / 100;
		break;
		
		case 3: //  180 - 239
		*red	= 0;
		*green	= 255 - (425 * (hue - 180)) / 100;
		*blue	= 255;
		break;
		
		case 4: //  240 - 299
		*red	= (425 * (hue - 240)) / 100;
		*green	= 0;
		*blue	= 255;
		break;
		
		case 5: //  300 - 359
		*red	= 255;
		*green	= 0;
		*blue	= 255 - ((425 * (hue - 300)) / 100);
		break;
	}
	
	saturation = 100 - saturation;
	uint8_t diff = 0;
	
	diff = ((255 - *red) * saturation) / 100;
	*red = *red + diff;
	
	diff = ((255 - *green) * saturation) / 100;
	*green = *green + diff;
	
	diff = ((255 - *blue) * saturation) / 100;
	*blue = *blue + diff;

	*red = (*red * value) / 100;
	*green = (*green * value) / 100;
	*blue = (*blue * value) / 100;
}

Hallo sschultewolter
Das Problem ist schlimmer als Du glaubst.
Nicht nur daß 1, 2 oder 3 Farben zusammen eine andere Helligkeit ergeben als 1 Farbe alleine und das Auge ist nicht gleichmäßig empfindlich auf alle Farben bzw die Helligkeiten werden anders (nicht linear) empfunden; auch die LED der 3 Grundfarben haben verschiedene maximale Helligkeit. Das könnte man aber mit einem Korrekturfaktor je Farbe kompensieren, damit ein weiß ein neutrales weiß ergibt (Farbtemperatur 6500K)

Ich habe diesen Sketch gefunden, welcher aber subjektiv auch nicht einen konstante Helligkeit der verschiedenen Farben ergibt.

void HSVtoRGB(int hue, int sat, int val, int colors[3]) 
	{
	// hue: 0-359, sat: 0-255, val (lightness): 0-255
	int r, g, b, base;
	if (sat == 0) 
		{                     // Achromatic color (gray).
		colors[0] = val;
		colors[1] = val;
		colors[2] = val;
		} 
	else  
		{
		base = ((255 - sat) * val) >> 8;
		switch(hue / 60) 
			{
			case 0:
				r = val;
				g = (((val - base) * hue) / 60) + base;
				b = base;
				break;
			case 1:
				r = (((val - base) * (60 - (hue % 60))) / 60) + base;
				g = val;
				b = base;
				break;
			case 2:
				r = base;
				g = val;
				b = (((val - base) * (hue % 60)) / 60) + base;
				break;
			case 3:
				r = base;
				g = (((val - base) * (60 - (hue % 60))) / 60) + base;
				b = val;
				break;
			case 4:
				r = (((val - base) * (hue % 60)) / 60) + base;
				g = base;
				b = val;
				break;
			case 5:
				r = val;
				g = base;
				b = (((val - base) * (60 - (hue % 60))) / 60) + base;
				break;
			}
			colors[0] = r;
			colors[1] = g;
			colors[2] = b;
		}
	}

Die Antwort ist Gammakorrektur. Gammakorrektur – Wikipedia

Hier ausfühlich inkl. Code erklärt: The Issue | LED Tricks: Gamma Correction | Adafruit Learning System

Das kombiniert man noch mit einer Farbkalibrierung / Weißabgleich und schon hat man korrekte Farben und Intensitäten.

Letzteres ist übrigens sogar bei den FastLED Examples mit dabei...

Das Problem ist nicht die HSV nach RGB Umrechnung, sondern eine normalisierte RGB Ausgabe.

Gelb in identischer WAHRGENOMMENER Helligkeit ist eben nicht 255 R + 255 G, sondern WENIGER als die Hälfte.

Die Helligkeitswahrnehmung des Auges ist über das Farbspektrum ungleichmäßig verteilt.
http://www.psychologie.uni-heidelberg.de/ae/allg/lehre/wct/w/w4_helligkeit/w440_wellenlaenge.htm

Grüße

Helmuth

Danke Helmut, werde mir das heute Abend mal anschauen. Hab im anderen Forum (mikrokontroller) auch entsprechende Tipps bereits bekommen, die basieren aber nicht auf deiner Lösung.

Die FastLED hat einiges dabei. Nutzte diese aber nicht, da die für die kleinen Zwerge teils einfach zu überladen ist. Da bekomme ich den Speicher immer sehr schnell voll.

Eine Farbkorrektur hatte ich bislang nur über alle Farben drin (wichtig fürs lineare Fading, stammt irgendwo aus dem Forum, wenn nicht sogar von dir ;))