URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-09-21 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add new algorithm for conversion HSL to RGB.
* mln/fun/v2v/hsl_to_rgb.hh: Add new algorithm for conversion.
* mln/value/rgb.hh: Enable convertion to HSL.
---
fun/v2v/hsl_to_rgb.hh | 87 +++++++++++++++++++++++++++++++++++---------------
value/rgb.hh | 50 ++++++++++++++--------------
2 files changed, 86 insertions(+), 51 deletions(-)
Index: trunk/milena/mln/value/rgb.hh
===================================================================
--- trunk/milena/mln/value/rgb.hh (revision 4513)
+++ trunk/milena/mln/value/rgb.hh (revision 4514)
@@ -29,7 +29,7 @@
# include <mln/value/ops.hh>
-// # include <mln/fun/v2v/hsl_to_rgb.hh>
+# include <mln/fun/v2v/hsl_to_rgb.hh>
# include <mln/value/concept/vectorial.hh>
# include <mln/value/int_u.hh>
# include <mln/algebra/vec.hh>
@@ -42,24 +42,24 @@
-// namespace fun
-// {
+ namespace fun
+ {
-// namespace v2v
-// {
+ namespace v2v
+ {
-// template <typename T_rgb>
-// struct f_hsl_to_rgb_;
+ template <typename T_rgb>
+ struct f_hsl_to_rgb_;
-// typedef f_hsl_to_rgb_< value::rgb<8> > f_hsl_to_rgb_3x8_t;
+ typedef f_hsl_to_rgb_< value::rgb<8> > f_hsl_to_rgb_3x8_t;
// typedef f_hsl_to_rgb_< value::rgb<16> > f_hsl_to_rgb_3x16_t;
-// extern f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
+ extern f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
// extern f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16;
-// }
+ }
-// }
+ }
namespace literal
@@ -90,11 +90,11 @@
}
-// // Forward declaration.
-// namespace value
-// {
-// template <typename H, typename S, typename L> class hsl_;
-// }
+ // Forward declaration.
+ namespace value
+ {
+ template <typename H, typename S, typename L> class hsl_;
+ }
namespace convert
@@ -115,9 +115,9 @@
template <unsigned m>
void from_to_(const value::int_u<m>& from, value::rgb<m>& to);
-// // hsl -> rgb8.
-// template <typename H, typename S, typename L>
-// void from_to_(const value::hsl_<H,S,L>&, value::rgb<8>&
to);
+ // hsl -> rgb8.
+ template <typename H, typename S, typename L>
+ void from_to_(const value::hsl_<H,S,L>&, value::rgb<8>& to);
// // hsl -> rgb16.
// template <typename H, typename S, typename L>
@@ -791,12 +791,12 @@
to = value::rgb<m>(from, from, from);
}
-// template <typename H, typename S, typename L>
-// void
-// from_to_(const value::hsl_<H,S,L>& from, value::rgb<8>& to)
-// {
-// to = fun::v2v::f_hsl_to_rgb_3x8(from);
-// }
+ template <typename H, typename S, typename L>
+ void
+ from_to_(const value::hsl_<H,S,L>& from, value::rgb<8>& to)
+ {
+ to = fun::v2v::f_hsl_to_rgb_3x8(from);
+ }
// template <typename H, typename S, typename L>
// void
Index: trunk/milena/mln/fun/v2v/hsl_to_rgb.hh
===================================================================
--- trunk/milena/mln/fun/v2v/hsl_to_rgb.hh (revision 4513)
+++ trunk/milena/mln/fun/v2v/hsl_to_rgb.hh (revision 4514)
@@ -92,40 +92,75 @@
/// \}
+ // This method implement the conversion from HSL to RGB
+ // explained by Wikipedia.
+ // url:
http://en.wikipedia.org/wiki/HSL_and_HSV
template <typename T_rgb>
template <typename T_hsl>
inline
T_rgb
f_hsl_to_rgb_<T_rgb>::operator()(const T_hsl& hsl) const
{
- typedef typename T_rgb::red_t red_t;
- typedef typename T_rgb::green_t green_t;
- typedef typename T_rgb::blue_t blue_t;
-
- static math::round<red_t> to_r;
- static math::round<green_t> to_g;
- static math::round<blue_t> to_b;
-
- static const float
- sqrt3_3 = std::sqrt(3.0f) / 3.0f,
- inv_sqrt6 = 1 / std::sqrt(6.0f),
- inv_sqrt2 = 1 / std::sqrt(2.0f);
-
- float
- h = hsl.hue() / 180.0 * 3.1415,
- alpha = hsl.sat() * std::cos(h),
- beta = hsl.sat() * std::sin(h);
-
-
- red_t r = to_r(sqrt3_3 * hsl.lum() + 2 * inv_sqrt6 * beta);
- green_t g =
- to_g(sqrt3_3 * hsl.lum() + inv_sqrt2 * alpha - inv_sqrt6 * beta);
- blue_t b =
- to_b(sqrt3_3 * hsl.lum() - inv_sqrt2 * alpha - inv_sqrt6 * beta);
+ const float q = (hsl.lum() < 0.5) ? hsl.lum() * (1.0 + hsl.sat()) :
+ hsl.lum() + hsl.sat() - (hsl.lum() * hsl.sat());
+ const float p = 2.0 * hsl.lum() - q;
+ const float hk = hsl.hue() / 360.0; // hk = normalized hue
+ float tr = hk + (1.0 / 3.0);
+ float tg = hk;
+ float tb = hk - (1.0 / 3.0);
+
+ if (tr < 0.0)
+ tr += 1.0;
+ if (tr > 1.0)
+ tr -= 1.0;
+
+ if (tg < 0.0)
+ tg += 1.0;
+ if (tg > 1.0)
+ tg -= 1.0;
+
+ if (tb < 0.0)
+ tb += 1.0;
+ if (tb > 1.0)
+ tb -= 1.0;
+
+ // Red.
+ float red;
+ if (tr < (1.0 / 6.0))
+ red = p + ((q - p) * 6 * tr);
+ else if (tr < (1.0 / 2.0))
+ red = q;
+ else if (tr < (2.0 / 3.0))
+ red = p + ((q - p) * 6 * ((2.0 / 3.0) - tr));
+ else
+ red = p;
+
+ // Green.
+ float green;
+ if (tg < (1.0 / 6.0))
+ green = p + ((q - p) * 6 * tg);
+ else if (tg < (1.0 / 2.0))
+ green = q;
+ else if (tg < (2.0 / 3.0))
+ green = p + ((q - p) * 6 * ((2.0 / 3.0) - tg));
+ else
+ green = p;
+
+ // Blue.
+ float blue;
+ if (tb < (1.0 / 6.0))
+ blue = p + ((q - p) * 6 * tb);
+ else if (tb < (1.0 / 2.0))
+ blue = q;
+ else if (tb < (2.0 / 3.0))
+ blue = p + ((q - p) * 6 * ((2.0 / 3.0) - tb));
+ else
+ blue = p;
- T_rgb rgb(r, g, b);
+ // Each component is in [0, 1].
+ T_rgb rgb_result(red * 255, green * 255, blue * 255);
- return rgb;
+ return rgb_result;
}
# endif // !MLN_INCLUDE_ONLY