Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
+ hsl and hsv colour spaces (boost/gil/extensions)
- Loading branch information
Showing
2 changed files
with
494 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.