diff --git a/src/lol/image/color.h b/src/lol/image/color.h index 10c5665a..d0dcd031 100644 --- a/src/lol/image/color.h +++ b/src/lol/image/color.h @@ -103,6 +103,31 @@ public: return vec4(RGBToHSV(src.rgb), src.a); } + /* + * Convert RGB to HSL + */ + static vec3 RGBToHSL(vec3 src) + { + float K = 0.f; + + if (src.g < src.b) + src = src.rbg, K = -1.f; + + if (src.r < src.g) + src = src.grb, K = -2.f / 6.f - K; + + float chroma = src.r - min(src.g, src.b); + float luma = src.r + min(src.g, src.b); + return vec3(abs(K + (src.g - src.b) / (6.f * chroma + 1e-20f)), + chroma / (min(luma, 2.f - luma) + 1e-20f), + 0.5f * luma); + } + + static vec4 RGBToHSL(vec4 src) + { + return vec4(RGBToHSL(src.rgb), src.a); + } + /* * Convert linear HSV to linear HSL */ diff --git a/test/unit/color.cpp b/test/unit/color.cpp index 9cb15ae1..76abaabb 100644 --- a/test/unit/color.cpp +++ b/test/unit/color.cpp @@ -101,6 +101,22 @@ LOLUNIT_FIXTURE(ColorTest) LOLUNIT_ASSERT_DOUBLES_EQUAL(v1.b, v2.b, 0.0001); } } + + LOLUNIT_TEST(RGBToHSL) + { + for (int r = 0; r < 20; r++) + for (int g = 0; g < 20; g++) + for (int b = 0; b < 20; b++) + { + vec3 v1 = vec3(r / 20.f, g / 20.f, b / 20.f); + vec3 v2 = Color::RGBToHSL(v1); + vec3 v3 = Color::HSVToHSL(Color::RGBToHSV(v1)); + + LOLUNIT_ASSERT_DOUBLES_EQUAL(v2.x, v3.x, 0.0001); + LOLUNIT_ASSERT_DOUBLES_EQUAL(v2.y, v3.y, 0.0001); + LOLUNIT_ASSERT_DOUBLES_EQUAL(v2.z, v3.z, 0.0001); + } + } }; } /* namespace lol */