TuttleOFX  1
clamp.hpp
Go to the documentation of this file.
00001 #ifndef _TERRY_CLAMP_HPP_
00002 #define _TERRY_CLAMP_HPP_
00003 
00004 #include <terry/color_processed_view.hpp>
00005 
00006 namespace terry {
00007 
00008 template <typename Channel>
00009 struct channel_clamp
00010 {
00011         typedef typename channel_base_type<Channel>::type ChannelBaseType;
00012         
00013         const ChannelBaseType _min;
00014         const ChannelBaseType _max;
00015 
00016         channel_clamp( const Channel min, const Channel max )
00017         : _min( min )
00018         , _max( max )
00019         { }
00020 
00021         GIL_FORCEINLINE
00022                 void operator( )(const Channel& src, Channel& dst ) const
00023         {
00024                 dst = std::min( _max, std::max( _min, ChannelBaseType(src) ) );
00025         }
00026 };
00027 
00028 template<typename Pixel>
00029 struct clamp_converter
00030 {
00031         typedef typename boost::gil::channel_type<Pixel>::type Channel;
00032 
00033         const Channel _min;
00034         const Channel _max;
00035 
00036         clamp_converter( )
00037         : _min( boost::gil::channel_traits<Channel>::min_value( ) )
00038         , _max( boost::gil::channel_traits<Channel>::max_value( ) )
00039         { }
00040 
00041         clamp_converter( const Channel min, const Channel max )
00042         : _min( min )
00043         , _max( max )
00044         { }
00045 
00046         GIL_FORCEINLINE
00047                 void operator( )(const Pixel& src, Pixel & dst ) const
00048         {
00049                 using namespace boost::gil;
00050                 static_for_each( src, dst, channel_clamp<Channel>( _min, _max ) );
00051         }
00052 };
00053 
00054 
00055 namespace detail {
00056 
00057 template<class View, class has_scoped_channel>
00058 struct clamp_view_type_resolver
00059 {
00060         typedef typename detail::color_processed_view_type<clamp_converter<typename View::value_type>,View>::type Result;
00061         
00062         inline Result clamp_view( const View& src )
00063         {
00064                 typedef typename View::value_type Pixel;
00065                 return color_processed_view( src, clamp_converter<Pixel>() );
00066         }
00067 };
00068 
00069 template<class View>
00070 struct clamp_view_type_resolver<View, boost::mpl::false_>
00071 {
00072         typedef View Result;
00073         
00074         inline Result clamp_view( const View& src )
00075         {
00076                 return src;
00077         }
00078 };
00079 
00080 /**
00081  * @brief Just an optimization to disable the process if the view don't use
00082  *        a scoped_channel_value. Without scoped_vhannel_value, we directly use
00083  *        the primitive type with the full range of this type. So there is
00084  *        nothing to clamp in this case. The values can't be outside the type
00085  *        range.
00086  */
00087 template<class View>
00088 struct clamp_view_type
00089 {
00090         typedef typename channel_type<View>::type Channel;
00091         
00092         typedef clamp_view_type_resolver<View, typename is_scoped_channel<Channel>::type > Resolver;
00093         
00094         inline typename Resolver::Result clamp_view( const View& src )
00095         {
00096                 return Resolver::clamp_view( src );
00097         }
00098 };
00099 
00100 }
00101 
00102 template <typename View>
00103 inline typename detail::color_processed_view_type<clamp_converter<typename View::value_type>,View>::type
00104 clamp_view( const View& src )
00105 {
00106         typedef typename View::value_type Pixel;
00107         return color_processed_view( src, clamp_converter<Pixel>() );
00108 }
00109 
00110 }
00111 
00112 #endif
00113