channel_algorithm.hppGo to the documentation of this file.00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 00004 Use, modification and distribution are subject to the Boost Software License, 00005 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 00006 http://www.boost.org/LICENSE_1_0.txt). 00007 00008 See http://opensource.adobe.com/gil for most recent version including documentation. 00009 */ 00010 /*************************************************************************************************/ 00011 00012 #ifndef GIL_CHANNEL_ALGORITHM_HPP 00013 #define GIL_CHANNEL_ALGORITHM_HPP 00014 00025 00026 #include "gil_config.hpp" 00027 #include "channel.hpp" 00028 #include <boost/mpl/less.hpp> 00029 #include <boost/mpl/integral_c.hpp> 00030 #include <boost/mpl/greater.hpp> 00031 #include <boost/type_traits.hpp> 00032 00033 namespace boost { namespace gil { 00034 00035 //#ifdef _MSC_VER 00036 //#pragma warning(push) 00037 //#pragma warning(disable: 4309) // disable truncation of constant value warning (using -1 to get the max value of an integral) 00038 //#endif 00039 00040 namespace detail { 00041 00042 // some forward declarations 00043 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral> struct channel_converter_unsigned_impl; 00044 template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater> struct channel_converter_unsigned_integral; 00045 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible> struct channel_converter_unsigned_integral_impl; 00046 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger> struct channel_converter_unsigned_integral_nondivisible; 00047 00051 00052 00053 template <typename UnsignedIntegralChannel> 00054 struct unsigned_integral_max_value : public mpl::integral_c<UnsignedIntegralChannel,-1> {}; 00055 00056 template <> 00057 struct unsigned_integral_max_value<uint8_t> : public mpl::integral_c<uint32_t,0xFF> {}; 00058 template <> 00059 struct unsigned_integral_max_value<uint16_t> : public mpl::integral_c<uint32_t,0xFFFF> {}; 00060 template <> 00061 struct unsigned_integral_max_value<uint32_t> : public mpl::integral_c<uintmax_t,0xFFFFFFFF> {}; 00062 00063 00064 template <int K> 00065 struct unsigned_integral_max_value<packed_channel_value<K> > 00066 : public mpl::integral_c<typename packed_channel_value<K>::integer_t, (1<<K)-1> {}; 00067 00071 00072 template <typename UnsignedIntegralChannel> 00073 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {}; 00074 00075 template <int K> 00076 struct unsigned_integral_num_bits<packed_channel_value<K> > 00077 : public mpl::int_<K> {}; 00078 00079 } // namespace detail 00080 00114 00115 00116 00117 00118 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept 00119 struct channel_converter_unsigned 00120 : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {}; 00121 00122 00124 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {}; 00125 00126 00127 namespace detail { 00128 00132 00134 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral> 00135 struct channel_converter_unsigned_impl : public std::unary_function<DstChannelV,SrcChannelV> { 00136 DstChannelV operator()(SrcChannelV src) const { 00137 return DstChannelV(channel_traits<DstChannelV>::min_value() + 00138 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>()); 00139 } 00140 private: 00141 template <typename C> 00142 static double channel_range() { 00143 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value()); 00144 } 00145 }; 00146 00147 // When both the source and the destination are integral channels, perform a faster conversion 00148 template <typename SrcChannelV, typename DstChannelV> 00149 struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true> 00150 : public channel_converter_unsigned_integral<SrcChannelV,DstChannelV, 00151 mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {}; 00152 00153 00157 00158 template <typename SrcChannelV, typename DstChannelV> 00159 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true> 00160 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true, 00161 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {}; 00162 00163 template <typename SrcChannelV, typename DstChannelV> 00164 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false> 00165 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false, 00166 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {}; 00167 00168 00172 00173 // Both source and destination are unsigned integral channels, 00174 // the src max value is less than the dst max value, 00175 // and the dst max value is divisible by the src max value 00176 template <typename SrcChannelV, typename DstChannelV> 00177 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> { 00178 DstChannelV operator()(SrcChannelV src) const { 00179 typedef typename unsigned_integral_max_value<DstChannelV>::value_type integer_t; 00180 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value; 00181 return DstChannelV(src * mul); 00182 } 00183 }; 00184 00185 // Both source and destination are unsigned integral channels, 00186 // the dst max value is less than (or equal to) the src max value, 00187 // and the src max value is divisible by the dst max value 00188 template <typename SrcChannelV, typename DstChannelV> 00189 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> { 00190 DstChannelV operator()(SrcChannelV src) const { 00191 typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t; 00192 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value; 00193 static const integer_t div2 = div/2; 00194 return DstChannelV((src + div2) / div); 00195 } 00196 }; 00197 00198 // Prevent overflow for the largest integral type 00199 template <typename DstChannelV> 00200 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> { 00201 DstChannelV operator()(uintmax_t src) const { 00202 static const uintmax_t div = unsigned_integral_max_value<bits32>::value / unsigned_integral_max_value<DstChannelV>::value; 00203 static const uintmax_t div2 = div/2; 00204 if (src > unsigned_integral_max_value<uintmax_t>::value - div2) 00205 return unsigned_integral_max_value<DstChannelV>::value; 00206 return DstChannelV((src + div2) / div); 00207 } 00208 }; 00209 00210 // Both source and destination are unsigned integral channels, 00211 // and the dst max value is not divisible by the src max value 00212 // See if you can represent the expression (src * dst_max) / src_max in integral form 00213 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst> 00214 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false> 00215 : public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst, 00216 mpl::greater< 00217 mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >, 00218 unsigned_integral_num_bits<uintmax_t> 00219 >::value> {}; 00220 00221 00222 // Both source and destination are unsigned integral channels, 00223 // the src max value is less than the dst max value, 00224 // and the dst max value is not divisible by the src max value 00225 // The expression (src * dst_max) / src_max fits in an integer 00226 template <typename SrcChannelV, typename DstChannelV> 00227 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> { 00228 DstChannelV operator()(SrcChannelV src) const { 00229 typedef typename detail::min_fast_uint<unsigned_integral_num_bits<SrcChannelV>::value+unsigned_integral_num_bits<DstChannelV>::value>::type integer_t; 00230 return DstChannelV(integer_t(src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value); 00231 } 00232 }; 00233 00234 // Both source and destination are unsigned integral channels, 00235 // the src max value is less than the dst max value, 00236 // and the dst max value is not divisible by the src max value 00237 // The expression (src * dst_max) / src_max cannot fit in an integer (overflows). Use a double 00238 template <typename SrcChannelV, typename DstChannelV> 00239 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> { 00240 DstChannelV operator()(SrcChannelV src) const { 00241 static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value); 00242 return DstChannelV(src * mul); 00243 } 00244 }; 00245 00246 00247 // Both source and destination are unsigned integral channels, 00248 // the dst max value is less than (or equal to) the src max value, 00249 // and the src max value is not divisible by the dst max value 00250 template <typename SrcChannelV, typename DstChannelV, bool CannotFit> 00251 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> { 00252 DstChannelV operator()(SrcChannelV src) const { 00253 typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t; 00254 00255 static const double div = unsigned_integral_max_value<SrcChannelV>::value / double(unsigned_integral_max_value<DstChannelV>::value); 00256 static const integer_t div2 = integer_t(div/2); 00257 return DstChannelV((src + div2) / div); 00258 } 00259 }; 00260 00261 } // namespace detail 00262 00266 00267 template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> { 00268 DstChannelV operator()(bits32f x) const { return DstChannelV(x*channel_traits<DstChannelV>::max_value()+0.5f); } 00269 }; 00270 00271 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> { 00272 bits32f operator()(SrcChannelV x) const { return bits32f(x/float(channel_traits<SrcChannelV>::max_value())); } 00273 }; 00274 00275 template <> struct channel_converter_unsigned<bits32f,bits32f> : public std::unary_function<bits32f,bits32f> { 00276 bits32f operator()(bits32f x) const { return x; } 00277 }; 00278 00279 00281 template <> struct channel_converter_unsigned<bits32,bits32f> : public std::unary_function<bits32,bits32f> { 00282 bits32f operator()(bits32 x) const { 00283 // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of bits32 matches max_value of bits32f 00284 if (x>=channel_traits<bits32>::max_value()) return channel_traits<bits32f>::max_value(); 00285 return float(x) / float(channel_traits<bits32>::max_value()); 00286 } 00287 }; 00289 template <> struct channel_converter_unsigned<bits32f,bits32> : public std::unary_function<bits32f,bits32> { 00290 bits32 operator()(bits32f x) const { 00291 // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of bits32 matches max_value of bits32f 00292 if (x>=channel_traits<bits32f>::max_value()) return channel_traits<bits32>::max_value(); 00293 return bits32(x * channel_traits<bits32>::max_value() + 0.5f); 00294 } 00295 }; 00296 00298 00299 namespace detail { 00300 // Converting from signed to unsigned integral channel. 00301 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type) 00302 template <typename ChannelValue> // Model ChannelValueConcept 00303 struct channel_convert_to_unsigned : public detail::identity<ChannelValue> { 00304 typedef ChannelValue type; 00305 }; 00306 00307 template <> struct channel_convert_to_unsigned<bits8s> : public std::unary_function<bits8s,bits8> { 00308 typedef bits8 type; 00309 type operator()(bits8s val) const { return val+128; } 00310 }; 00311 00312 template <> struct channel_convert_to_unsigned<bits16s> : public std::unary_function<bits16s,bits16> { 00313 typedef bits16 type; 00314 type operator()(bits16s val) const { return val+32768; } 00315 }; 00316 00317 template <> struct channel_convert_to_unsigned<bits32s> : public std::unary_function<bits32s,bits32> { 00318 typedef bits32 type; 00319 type operator()(bits32s x) const { return static_cast<bits32>(x+(1<<31)); } 00320 }; 00321 00322 00323 // Converting from unsigned to signed integral channel 00324 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type) 00325 template <typename ChannelValue> // Model ChannelValueConcept 00326 struct channel_convert_from_unsigned : public detail::identity<ChannelValue> { 00327 typedef ChannelValue type; 00328 }; 00329 00330 template <> struct channel_convert_from_unsigned<bits8s> : public std::unary_function<bits8,bits8s> { 00331 typedef bits8s type; 00332 type operator()(bits8 val) const { return val-128; } 00333 }; 00334 00335 template <> struct channel_convert_from_unsigned<bits16s> : public std::unary_function<bits16,bits16s> { 00336 typedef bits16s type; 00337 type operator()(bits16 val) const { return val-32768; } 00338 }; 00339 00340 template <> struct channel_convert_from_unsigned<bits32s> : public std::unary_function<bits32,bits32s> { 00341 typedef bits32s type; 00342 type operator()(bits32 x) const { return static_cast<bits32s>(x-(1<<31)); } 00343 }; 00344 00345 } // namespace detail 00346 00349 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept 00350 struct channel_converter : public std::unary_function<SrcChannelV,DstChannelV> { 00351 DstChannelV operator()(SrcChannelV src) const { 00352 typedef detail::channel_convert_to_unsigned<SrcChannelV> to_unsigned; 00353 typedef detail::channel_convert_from_unsigned<DstChannelV> from_unsigned; 00354 typedef channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type> converter_unsigned; 00355 return from_unsigned()(converter_unsigned()(to_unsigned()(src))); 00356 } 00357 }; 00358 00361 template <typename DstChannel, typename SrcChannel> // Model ChannelConcept (could be channel references) 00362 inline typename channel_traits<DstChannel>::value_type channel_convert(SrcChannel src) { 00363 return channel_converter<typename channel_traits<SrcChannel>::value_type, 00364 typename channel_traits<DstChannel>::value_type>()(src); 00365 } 00366 00371 struct default_channel_converter { 00372 template <typename Ch1, typename Ch2> 00373 void operator()(const Ch1& src, Ch2& dst) const { 00374 dst=channel_convert<Ch2>(src); 00375 } 00376 }; 00377 00378 namespace detail { 00379 // fast integer division by 255 00380 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; } 00381 00382 // fast integer divison by 32768 00383 inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; } 00384 } 00385 00399 00400 00402 template <typename ChannelValue> 00403 struct channel_multiplier_unsigned : public std::binary_function<ChannelValue,ChannelValue,ChannelValue> { 00404 ChannelValue operator()(ChannelValue a, ChannelValue b) const { 00405 return ChannelValue(a / double(channel_traits<ChannelValue>::max_value()) * b); 00406 } 00407 }; 00408 00410 template<> struct channel_multiplier_unsigned<bits8> : public std::binary_function<bits8,bits8,bits8> { 00411 bits8 operator()(bits8 a, bits8 b) const { return bits8(detail::div255(uint32_t(a) * uint32_t(b))); } 00412 }; 00413 00415 template<> struct channel_multiplier_unsigned<bits16> : public std::binary_function<bits16,bits16,bits16> { 00416 bits16 operator()(bits16 a, bits16 b) const { return bits16((uint32_t(a) * uint32_t(b))/65535); } 00417 }; 00418 00420 template<> struct channel_multiplier_unsigned<bits32f> : public std::binary_function<bits32f,bits32f,bits32f> { 00421 bits32f operator()(bits32f a, bits32f b) const { return a*b; } 00422 }; 00423 00425 template <typename ChannelValue> 00426 struct channel_multiplier : public std::binary_function<ChannelValue, ChannelValue, ChannelValue> { 00427 ChannelValue operator()(ChannelValue a, ChannelValue b) const { 00428 typedef detail::channel_convert_to_unsigned<ChannelValue> to_unsigned; 00429 typedef detail::channel_convert_from_unsigned<ChannelValue> from_unsigned; 00430 typedef channel_multiplier_unsigned<typename to_unsigned::result_type> multiplier_unsigned; 00431 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b))); 00432 } 00433 }; 00434 00436 template <typename Channel> // Models ChannelConcept (could be a channel reference) 00437 inline typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b) { 00438 return channel_multiplier<typename channel_traits<Channel>::value_type>()(a,b); 00439 } 00441 00456 00457 00458 template <typename Channel> // Models ChannelConcept (could be a channel reference) 00459 inline typename channel_traits<Channel>::value_type channel_invert(Channel x) { 00460 return channel_traits<Channel>::max_value()-x + channel_traits<Channel>::min_value(); 00461 } 00462 00463 //#ifdef _MSC_VER 00464 //#pragma warning(pop) 00465 //#endif 00466 00467 } } // namespace boost::gil 00468 00469 #endif Generated on Sat May 2 13:50:13 2009 for Generic Image Library by 1.5.6 |