Skip to content

Commit

Permalink
+ hsl and hsv colour spaces (boost/gil/extensions)
Browse files Browse the repository at this point in the history
  • Loading branch information
artemp committed Jun 17, 2012
1 parent 6281dec commit b9765ec
Show file tree
Hide file tree
Showing 2 changed files with 494 additions and 0 deletions.
263 changes: 263 additions & 0 deletions boost/gil/extension/toolbox/hsl.hpp
@@ -0,0 +1,263 @@
// Copyright 2007 Christian Henning.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

/*************************************************************************************************/

#ifndef GIL_HSL_H
#define GIL_HSL_H

////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Support for HSL color space
/// \author Christian Henning \n
////////////////////////////////////////////////////////////////////////////////////////

#include <boost/gil/gil_all.hpp>

namespace boost { namespace gil {

/// \addtogroup ColorNameModel
/// \{
namespace hsl_color_space
{
/// \brief Hue
struct hue_t {};
/// \brief Saturation
struct saturation_t {};
/// \brief Lightness
struct lightness_t {};
}
/// \}

/// \ingroup ColorSpaceModel
typedef mpl::vector3< hsl_color_space::hue_t
, hsl_color_space::saturation_t
, hsl_color_space::lightness_t
> hsl_t;

/// \ingroup LayoutModel
typedef layout<hsl_t> hsl_layout_t;


GIL_DEFINE_ALL_TYPEDEFS( 32f, hsl );

/// \ingroup ColorConvert
/// \brief RGB to HSL
template <>
struct default_color_converter_impl< rgb_t, hsl_t >
{
template <typename P1, typename P2>
void operator()( const P1& src, P2& dst ) const
{
using namespace hsl_color_space;

// only bits32f for hsl is supported
bits32f temp_red = channel_convert<bits32f>( get_color( src, red_t() ));
bits32f temp_green = channel_convert<bits32f>( get_color( src, green_t() ));
bits32f temp_blue = channel_convert<bits32f>( get_color( src, blue_t() ));

bits32f hue, saturation, lightness;

bits32f min_color = std::min( temp_red, std::min( temp_green, temp_blue ));
bits32f max_color = std::max( temp_red, std::max( temp_green, temp_blue ));

if ( max_color - min_color < 0.001 )
{
// rgb color is gray

hue = 0.f;
saturation = 0.f;

// doesn't matter which rgb channel we use.
lightness = temp_red;
}
else
{

bits32f diff = max_color - min_color;

// lightness calculation

lightness = ( min_color + max_color ) / 2.f;

// saturation calculation

if( lightness < 0.5f )
{
saturation = diff
/ ( min_color + max_color );
}
else
{
saturation = ( max_color - min_color )
/ ( 2.f - diff );

}

// hue calculation
if( std::abs( max_color - temp_red ) < 0.0001f )
{
// max_color is red
hue = ( temp_green - temp_blue )
/ diff;

}
else if( std::abs( max_color - temp_green) < 0.0001f )
{
// max_color is green
// 2.0 + (b - r) / (maxColor - minColor)
hue = 2.f
+ ( temp_blue - temp_red )
/ diff;

}
else
{
// max_color is blue
// 4.0 + (r - g) / (maxColor - minColor)
hue = 4.f
+ ( temp_red - temp_green )
/ diff;
}

hue /= 6.f;

if( hue < 0.f )
{
hue += 1.f;
}
}

get_color( dst,hue_t() ) = hue;
get_color( dst,saturation_t() ) = saturation;
get_color( dst,lightness_t() ) = lightness;
}
};

/// \ingroup ColorConvert
/// \brief HSL to RGB
template <>
struct default_color_converter_impl<hsl_t,rgb_t>
{
template <typename P1, typename P2>
void operator()( const P1& src, P2& dst) const
{
using namespace hsl_color_space;

bits32f red, green, blue;

if( std::abs( get_color( src, saturation_t() )) < 0.0001 )
{
// If saturation is 0, the color is a shade of gray
red = get_color( src, lightness_t() );
green = get_color( src, lightness_t() );
blue = get_color( src, lightness_t() );
}
else
{
float temp1, temp2;
float tempr, tempg, tempb;

//Set the temporary values
if( get_color( src, lightness_t() ) < 0.5 )
{
temp2 = get_color( src, lightness_t() )
* ( 1.f + get_color( src, saturation_t() ) );
}
else
{
temp2 = ( get_color( src, lightness_t() ) + get_color( src, saturation_t() ))
- ( get_color( src, lightness_t() ) * get_color( src, saturation_t() ));
}

temp1 = 2.f
* get_color( src, lightness_t() )
- temp2;

tempr = get_color( src, hue_t() ) + 1.f / 3.f;

if( tempr > 1.f )
{
tempr--;
}

tempg = get_color( src, hue_t() );
tempb = get_color( src, hue_t() ) - 1.f / 3.f;

if( tempb < 0.f )
{
tempb++;
}

//Red
if( tempr < 1.f / 6.f )
{
red = temp1 + ( temp2 - temp1 ) * 6.f * tempr;
}
else if( tempr < 0.5f )
{
red = temp2;
}
else if( tempr < 2.f / 3.f )
{
red = temp1 + (temp2 - temp1)
* (( 2.f / 3.f ) - tempr) * 6.f;
}
else
{
red = temp1;
}

//Green
if( tempg < 1.f / 6.f )
{
green = temp1 + ( temp2 - temp1 ) * 6.f * tempg;
}
else if( tempg < 0.5f )
{
green = temp2;
}
else if( tempg < 2.f / 3.f )
{
green = temp1 + ( temp2 - temp1 )
* (( 2.f / 3.f ) - tempg) * 6.f;
}
else
{
green = temp1;
}

//Blue
if( tempb < 1.f / 6.f )
{
blue = temp1 + (temp2 - temp1) * 6.f * tempb;
}
else if( tempb < 0.5f )
{
blue = temp2;
}
else if( tempb < 2.f / 3.f )
{
blue = temp1 + (temp2 - temp1)
* (( 2.f / 3.f ) - tempb) * 6.f;
}
else
{
blue = temp1;
}
}

get_color(dst,red_t()) =
channel_convert<typename color_element_type< P2, red_t >::type>( red );
get_color(dst,green_t())=
channel_convert<typename color_element_type< P2, green_t >::type>( green );
get_color(dst,blue_t()) =
channel_convert<typename color_element_type< P2, blue_t >::type>( blue );
}
};

} } // namespace boost::gil

#endif // GIL_HSL_H

0 comments on commit b9765ec

Please sign in to comment.