/* Read http://z0b.kapsi.fi/snippets.php before using this code. Thank you. */ #include // min/max #include // fabs #include // RGB -> HSL void convertRGBToHSL(const uint8_t red, const uint8_t green, const uint8_t blue, uint8_t &hue, uint8_t &sat, uint8_t &lum) { const float r = (float)red / 255.0f, g = (float)green / 255.0f, b = (float)blue / 255.0f; // find min/max color values const float minColor = std::min(r, std::min(g, b)), maxColor = std::max(r, std::max(g, b)), diff = maxColor - minColor; if (std::fabs(diff) < 0.001f) { // colors are same, so it is a shade of grey lum = red; sat = 0U; hue = 0U; return; } // luminance const float l = (minColor + maxColor) / 2.0f; // saturation float s; if (l < 0.5f) s = diff / (maxColor + minColor); else s = diff / (2.0f - maxColor - minColor); // hue float h; if (std::fabs(maxColor - r) < 0.001f) h = (g - b) / diff; else if (std::fabs(maxColor - g) < 0.001f) h = 2.0f + (b - r) / diff; else h = 4.0f + (r - g) / diff; h /= 6.0f; if (h < 0.0f) h += 1.0f; // convert back to 0...255 range, with proper rounding hue = (uint8_t)(int(h * 255.0f + 0.5f) & 0xFF); sat = (uint8_t)(int(s * 255.0f + 0.5f) & 0xFF); lum = (uint8_t)(int(l * 255.0f + 0.5f) & 0xFF); } // HSL -> RGB void convertHSLToRGB(const uint8_t hue, const uint8_t sat, const uint8_t lum, uint8_t &red, uint8_t &green, uint8_t &blue) { if (sat == 0U) { // saturation is zero, so it is a shade of grey red = green = blue = lum; return; } // convert from 0...255 to 0...1 const float h = (float)hue / 255.0f, s = (float)sat / 255.0f, l = (float)lum / 255.0f; float q; if (l < 0.5f) q = l * (1.0f + s); else q = (l + s) - (l * s); const float p = (2.0f * l) - q; float t[3]; t[0] = h + (1.0f / 3.0f); t[1] = h; t[2] = h - (1.0f / 3.0f); for (int i = 0; i < 3; i++) { if (t[i] < 0.0f) t[i] += 1.0f; if (t[i] > 1.0f) t[i] -= 1.0f; } float out[3]; for (int i = 0; i < 3; i++) { if (t[i] * 6.0f < 1.0f) out[i] = p + (q - p) * 6.0f * t[i]; else if (t[i] * 2.0f < 1.0f) out[i] = q; else if (t[i] * 3.0f < 2.0f) out[i] = p + (q - p) * ((2.0f / 3.0f) - t[i]) * 6.0f; else out[i] = p; } // convert back to 0...255 range, with proper rounding red = (uint8_t)(int(out[0] * 255.0f + 0.5f) & 0xFF); green = (uint8_t)(int(out[1] * 255.0f + 0.5f) & 0xFF); blue = (uint8_t)(int(out[2] * 255.0f + 0.5f) & 0xFF); } #ifdef TEST #include // a small test program int main() { uint8_t r1, g1, b1, r2, g2, b2, h, s, l; // input color r1 = 77U; g1 = 125U; b1 = 213U; // convert to HSL then back convertRGBToHSL(r1, g1, b1, h, s, l); convertHSLToRGB(h, s, l, r2, g2, b2); // print all values printf(" IN: %d, %d, %d\n", r1, g1, b1); printf("HSL: %d, %d, %d\n", h, s, l); printf("OUT: %d, %d, %d\n", r2, g2, b2); return 0; } #endif