+ hsl and hsv colour spaces (boost/gil/extensions)
This commit is contained in:
parent
6281dec04b
commit
b9765ec1db
2 changed files with 494 additions and 0 deletions
263
boost/gil/extension/toolbox/hsl.hpp
Normal file
263
boost/gil/extension/toolbox/hsl.hpp
Normal file
|
@ -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
|
231
boost/gil/extension/toolbox/hsv.hpp
Normal file
231
boost/gil/extension/toolbox/hsv.hpp
Normal file
|
@ -0,0 +1,231 @@
|
|||
// Copyright 2004 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_HSV_H
|
||||
#define GIL_HSV_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Support for HSV color space
|
||||
/// \author Christian Henning \n
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/cast.hpp>
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \addtogroup ColorNameModel
|
||||
/// \{
|
||||
namespace hsv_color_space
|
||||
{
|
||||
/// \brief Hue
|
||||
struct hue_t {};
|
||||
/// \brief Saturation
|
||||
struct saturation_t{};
|
||||
/// \brief Value
|
||||
struct value_t {};
|
||||
}
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
typedef mpl::vector3< hsv_color_space::hue_t
|
||||
, hsv_color_space::saturation_t
|
||||
, hsv_color_space::value_t
|
||||
> hsv_t;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
typedef layout<hsv_t> hsv_layout_t;
|
||||
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS( 32f, hsv )
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to HSV
|
||||
template <>
|
||||
struct default_color_converter_impl< rgb_t, hsv_t >
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst ) const
|
||||
{
|
||||
using namespace hsv_color_space;
|
||||
|
||||
// only bits32f for hsv 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, value;
|
||||
|
||||
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 ));
|
||||
|
||||
value = max_color;
|
||||
|
||||
bits32f diff = max_color - min_color;
|
||||
|
||||
if( max_color < 0.0001f )
|
||||
{
|
||||
saturation = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
saturation = diff / max_color;
|
||||
}
|
||||
|
||||
|
||||
if( saturation < 0.0001f )
|
||||
{
|
||||
//it doesn't matter what value it has
|
||||
hue = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (std::abs)( boost::numeric_cast<int>(temp_red - max_color) ) < 0.0001f )
|
||||
{
|
||||
hue = ( temp_green - temp_blue )
|
||||
/ diff;
|
||||
}
|
||||
else if( temp_green == max_color )
|
||||
{
|
||||
hue = 2.f + ( temp_blue - temp_red )
|
||||
/ diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
hue = 4.f + ( temp_red - temp_green )
|
||||
/ diff;
|
||||
}
|
||||
|
||||
//to bring it to a number between 0 and 1
|
||||
hue /= 6.f;
|
||||
|
||||
if( hue < 0.f )
|
||||
{
|
||||
hue++;
|
||||
}
|
||||
}
|
||||
|
||||
get_color( dst, hue_t() ) = hue;
|
||||
get_color( dst, saturation_t() ) = saturation;
|
||||
get_color( dst, value_t() ) = value;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief HSV to RGB
|
||||
template <>
|
||||
struct default_color_converter_impl<hsv_t,rgb_t>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst) const
|
||||
{
|
||||
using namespace hsv_color_space;
|
||||
|
||||
bits32f red, green, blue;
|
||||
|
||||
//If saturation is 0, the color is a shade of gray
|
||||
if( abs( get_color( src, saturation_t() )) < 0.0001f )
|
||||
{
|
||||
// If saturation is 0, the color is a shade of gray
|
||||
red = get_color( src, value_t() );
|
||||
green = get_color( src, value_t() );
|
||||
blue = get_color( src, value_t() );
|
||||
}
|
||||
else
|
||||
{
|
||||
bits32f frac, p, q, t, h;
|
||||
bits32 i;
|
||||
|
||||
//to bring hue to a number between 0 and 6, better for the calculations
|
||||
h = get_color( src, hue_t() );
|
||||
h *= 6.f;
|
||||
|
||||
i = static_cast<bits32>( floor( h ));
|
||||
|
||||
frac = h - i;
|
||||
|
||||
p = get_color( src, value_t() )
|
||||
* ( 1.f - get_color( src, saturation_t() ));
|
||||
|
||||
q = get_color( src, value_t() )
|
||||
* ( 1.f - ( get_color( src, saturation_t() ) * frac ));
|
||||
|
||||
t = get_color( src, value_t() )
|
||||
* ( 1.f - ( get_color( src, saturation_t() ) * ( 1.f - frac )));
|
||||
|
||||
switch( i )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
red = get_color( src, value_t() );
|
||||
green = t;
|
||||
blue = p;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
red = q;
|
||||
green = get_color( src, value_t() );
|
||||
blue = p;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
red = p;
|
||||
green = get_color( src, value_t() );
|
||||
blue = t;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
red = p;
|
||||
green = q;
|
||||
blue = get_color( src, value_t() );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
red = t;
|
||||
green = p;
|
||||
blue = get_color( src, value_t() );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
red = get_color( src, value_t() );
|
||||
green = p;
|
||||
blue = q;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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_HSV_H
|
Loading…
Add table
Reference in a new issue