HSL To RGB for PIC Microcontrollers – and others

While the float versions of this function work wonderfully on PCs, the  PIC12F, not so much. Without a math coprocessor or FPU, additional libraries are loaded to handle the floats.

This function is a port of the float function which squeezed into 1830 bytes while this fits inside into 745ish bytes with no optimizations.
This function was only verified against hues at 50% saturation and 50% lightness.

 

// function prototypes
void HslToRgb(uint16_t hue, uint8_t saturation, uint8_t lightness);
uint8_t AdjustLightness(uint8_t color, int lightness);

// Hue:        0-360
// Saturation: 0-100
// Lightness:  0-100

void HslToRgb(uint16_t hue, uint8_t lightness, uint8_t saturation)
{
	/* based on Keenan Lidral-Porter's java function in
	 https://stackoverflow.com/questions/27653757/how-to-use-hsl-to-rgb-conversion-function
	 which is...
	 based on algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB
	 */

        while(hue>360) hue-=360;
        while(saturation>100) saturation-=100;
        while(lightness>100) lightness-=100;

	if (hue == 0) { r = g = b = 0; }

	uint16_t chroma = (1 - abs((2 * lightness) - 100)) * saturation;
	uint16_t huePrimet = hue * 10 / 6;
	uint16_t huePrime = huePrimet / 100;
	uint16_t fhPi = huePrimet - (huePrime * 100);

	if (hue < = 59) 			fhPi = 100 - fhPi;
	if (hue >= 120 && hue < = 179)		fhPi = 100 - fhPi;
	if (hue >= 240 && hue < = 299)		fhPi = 100 - fhPi;

	uint16_t secondComponent = (chroma * (100 - abs(fhPi))) / 100;

	int red = 0, green = 0, blue = 0;

	switch (huePrime)
	{
	case 0:
		red = chroma;
		green = secondComponent;
		break;
	case 1:
		red = secondComponent;
		green = chroma;
		break;
	case 2:
		green = chroma;
		blue = secondComponent;
		break;
	case 3:
		green = secondComponent;
		blue = chroma;
		break;
	case 4:
		red = secondComponent;
		blue = chroma;
		break;
	case 5:
		red = chroma;
		blue = secondComponent;
		break;
	}

	lightness = lightness - (chroma / 2);

	r = AdjustLightness(red, lightness);
	g = AdjustLightness(green, lightness);
	b = AdjustLightness(blue, lightness);
}

uint8_t AdjustLightness(uint8_t color, int lightness)
{
    return (color + lightness) * 255 / 100;
}

Leave a Reply