TuttleOFX
1
|
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