TuttleOFX
1
|
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 00015 //////////////////////////////////////////////////////////////////////////////////////// 00016 /// \file 00017 /// \brief Channel algorithms 00018 /// \author Lubomir Bourdev and Hailin Jin \n 00019 /// Adobe Systems Incorporated 00020 /// \date 2005-2007 \n Last updated on May 6, 2007 00021 /// 00022 /// Definitions of standard GIL 8-bit, 16-bit, 32-bit channels 00023 /// 00024 //////////////////////////////////////////////////////////////////////////////////////// 00025 00026 #include <boost/gil/gil_config.hpp> 00027 #include <boost/gil/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 00048 ////////////////////////////////////// 00049 //// unsigned_integral_max_value - given an unsigned integral channel type, returns its maximum value as an MPL integral constant 00050 ////////////////////////////////////// 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 00068 ////////////////////////////////////// 00069 //// unsigned_integral_num_bits - given an unsigned integral channel type, returns the minimum number of bits needed to represent it 00070 ////////////////////////////////////// 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 00081 /** 00082 \defgroup ChannelConvertAlgorithm channel_convert 00083 \brief Converting from one channel type to another 00084 \ingroup ChannelAlgorithm 00085 00086 Conversion is done as a simple linear mapping of one channel range to the other, 00087 such that the minimum/maximum value of the source maps to the minimum/maximum value of the destination. 00088 One implication of this is that the value 0 of signed channels may not be preserved! 00089 00090 When creating new channel models, it is often a good idea to provide specializations for the channel conversion algorithms, for 00091 example, for performance optimizations. If the new model is an integral type that can be signed, it is easier to define the conversion 00092 only for the unsigned type (\p channel_converter_unsigned) and provide specializations of \p detail::channel_convert_to_unsigned 00093 and \p detail::channel_convert_from_unsigned to convert between the signed and unsigned type. 00094 00095 Example: 00096 \code 00097 // bits32f is a floating point channel with range [0.0f ... 1.0f] 00098 bits32f src_channel = channel_traits<bits32f>::max_value(); 00099 assert(src_channel == 1); 00100 00101 // bits8 is 8-bit unsigned integral channel (typedef-ed from unsigned char) 00102 bits8 dst_channel = channel_convert<bits8>(src_channel); 00103 assert(dst_channel == 255); // max value goes to max value 00104 \endcode 00105 */ 00106 00107 /** 00108 \defgroup ChannelConvertUnsignedAlgorithm channel_converter_unsigned 00109 \ingroup ChannelConvertAlgorithm 00110 \brief Convert one unsigned/floating point channel to another. Converts both the channel type and range 00111 @{ 00112 */ 00113 00114 ////////////////////////////////////// 00115 //// channel_converter_unsigned 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 00123 /// \brief Converting a channel to itself - identity operation 00124 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {}; 00125 00126 00127 namespace detail { 00128 00129 ////////////////////////////////////// 00130 //// channel_converter_unsigned_impl 00131 ////////////////////////////////////// 00132 00133 /// \brief This is the default implementation. Performance specializatons are provided 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 00154 ////////////////////////////////////// 00155 //// channel_converter_unsigned_integral 00156 ////////////////////////////////////// 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 00169 ////////////////////////////////////// 00170 //// channel_converter_unsigned_integral_impl 00171 ////////////////////////////////////// 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 // Both source and destination are unsigned integral channels, 00247 // the dst max value is less than (or equal to) the src max value, 00248 // and the src max value is not divisible by the dst max value 00249 template <typename SrcChannelV, typename DstChannelV, bool CannotFit> 00250 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> { 00251 DstChannelV operator()(SrcChannelV src) const { 00252 00253 typedef typename detail::unsigned_integral_max_value< SrcChannelV >::value_type src_integer_t; 00254 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t; 00255 00256 static const double div = unsigned_integral_max_value<SrcChannelV>::value 00257 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value ); 00258 00259 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 ); 00260 00261 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div ))); 00262 } 00263 }; 00264 00265 } // namespace detail 00266 00267 ///////////////////////////////////////////////////// 00268 /// bits32f conversion 00269 ///////////////////////////////////////////////////// 00270 00271 template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> { 00272 DstChannelV operator()(bits32f x) const 00273 { 00274 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t; 00275 00276 const bits32f convertedValue = x * channel_traits<DstChannelV>::max_value() + 0.5f; 00277 const bits32f clampedValue = std::min( 00278 (bits32f)channel_traits<DstChannelV>::max_value(), 00279 std::max( (bits32f)channel_traits<DstChannelV>::min_value(), convertedValue ) ); 00280 00281 return DstChannelV( static_cast< dst_integer_t >(clampedValue) ); 00282 } 00283 }; 00284 00285 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> { 00286 bits32f operator()(SrcChannelV x) const { return bits32f(x/float(channel_traits<SrcChannelV>::max_value())); } 00287 }; 00288 00289 template <> struct channel_converter_unsigned<bits32f,bits32f> : public std::unary_function<bits32f,bits32f> { 00290 bits32f operator()(bits32f x) const { return x; } 00291 }; 00292 00293 00294 /// \brief 32 bit <-> float channel conversion 00295 template <> struct channel_converter_unsigned<bits32,bits32f> : public std::unary_function<bits32,bits32f> { 00296 bits32f operator()(bits32 x) const { 00297 // 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 00298 if (x>=channel_traits<bits32>::max_value()) return channel_traits<bits32f>::max_value(); 00299 return float(x) / float(channel_traits<bits32>::max_value()); 00300 } 00301 }; 00302 /// \brief 32 bit <-> float channel conversion 00303 template <> struct channel_converter_unsigned<bits32f,bits32> : public std::unary_function<bits32f,bits32> { 00304 bits32 operator()(bits32f x) const { 00305 // 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 00306 if (x>=channel_traits<bits32f>::max_value()) return channel_traits<bits32>::max_value(); 00307 return bits32(x * channel_traits<bits32>::max_value() + 0.5f); 00308 } 00309 }; 00310 00311 /// @} 00312 00313 namespace detail { 00314 // Converting from signed to unsigned integral channel. 00315 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type) 00316 template <typename ChannelValue> // Model ChannelValueConcept 00317 struct channel_convert_to_unsigned : public detail::identity<ChannelValue> { 00318 typedef ChannelValue type; 00319 }; 00320 00321 template <> struct channel_convert_to_unsigned<bits8s> : public std::unary_function<bits8s,bits8> { 00322 typedef bits8 type; 00323 type operator()(bits8s val) const { return val+128; } 00324 }; 00325 00326 template <> struct channel_convert_to_unsigned<bits16s> : public std::unary_function<bits16s,bits16> { 00327 typedef bits16 type; 00328 type operator()(bits16s val) const { return val+32768; } 00329 }; 00330 00331 template <> struct channel_convert_to_unsigned<bits32s> : public std::unary_function<bits32s,bits32> { 00332 typedef bits32 type; 00333 type operator()(bits32s x) const { return static_cast<bits32>(x+(1<<31)); } 00334 }; 00335 00336 00337 // Converting from unsigned to signed integral channel 00338 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type) 00339 template <typename ChannelValue> // Model ChannelValueConcept 00340 struct channel_convert_from_unsigned : public detail::identity<ChannelValue> { 00341 typedef ChannelValue type; 00342 }; 00343 00344 template <> struct channel_convert_from_unsigned<bits8s> : public std::unary_function<bits8,bits8s> { 00345 typedef bits8s type; 00346 type operator()(bits8 val) const { return val-128; } 00347 }; 00348 00349 template <> struct channel_convert_from_unsigned<bits16s> : public std::unary_function<bits16,bits16s> { 00350 typedef bits16s type; 00351 type operator()(bits16 val) const { return val-32768; } 00352 }; 00353 00354 template <> struct channel_convert_from_unsigned<bits32s> : public std::unary_function<bits32,bits32s> { 00355 typedef bits32s type; 00356 type operator()(bits32 x) const { return static_cast<bits32s>(x-(1<<31)); } 00357 }; 00358 00359 } // namespace detail 00360 00361 /// \ingroup ChannelConvertAlgorithm 00362 /// \brief A unary function object converting between channel types 00363 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept 00364 struct channel_converter : public std::unary_function<SrcChannelV,DstChannelV> { 00365 DstChannelV operator()(const SrcChannelV& src) const { 00366 typedef detail::channel_convert_to_unsigned<SrcChannelV> to_unsigned; 00367 typedef detail::channel_convert_from_unsigned<DstChannelV> from_unsigned; 00368 typedef channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type> converter_unsigned; 00369 return from_unsigned()(converter_unsigned()(to_unsigned()(src))); 00370 } 00371 }; 00372 00373 /// \ingroup ChannelConvertAlgorithm 00374 /// \brief Converting from one channel type to another. 00375 template <typename DstChannel, typename SrcChannel> // Model ChannelConcept (could be channel references) 00376 inline typename channel_traits<DstChannel>::value_type channel_convert(const SrcChannel& src) { 00377 return channel_converter<typename channel_traits<SrcChannel>::value_type, 00378 typename channel_traits<DstChannel>::value_type>()(src); 00379 } 00380 00381 /// \ingroup ChannelConvertAlgorithm 00382 /// \brief Same as channel_converter, except it takes the destination channel by reference, which allows 00383 /// us to move the templates from the class level to the method level. This is important when invoking it 00384 /// on heterogeneous pixels. 00385 struct default_channel_converter { 00386 template <typename Ch1, typename Ch2> 00387 void operator()(const Ch1& src, Ch2& dst) const { 00388 dst=channel_convert<Ch2>(src); 00389 } 00390 }; 00391 00392 namespace detail { 00393 // fast integer division by 255 00394 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; } 00395 00396 // fast integer divison by 32768 00397 inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; } 00398 } 00399 00400 /** 00401 \defgroup ChannelMultiplyAlgorithm channel_multiply 00402 \ingroup ChannelAlgorithm 00403 \brief Multiplying unsigned channel values of the same type. Performs scaled multiplication result = a * b / max_value 00404 00405 Example: 00406 \code 00407 bits8 x=128; 00408 bits8 y=128; 00409 bits8 mul = channel_multiply(x,y); 00410 assert(mul == 64); // 64 = 128 * 128 / 255 00411 \endcode 00412 */ 00413 /// @{ 00414 00415 /// \brief This is the default implementation. Performance specializatons are provided 00416 template <typename ChannelValue> 00417 struct channel_multiplier_unsigned : public std::binary_function<ChannelValue,ChannelValue,ChannelValue> { 00418 ChannelValue operator()(ChannelValue a, ChannelValue b) const { 00419 return ChannelValue(a / double(channel_traits<ChannelValue>::max_value()) * b); 00420 } 00421 }; 00422 00423 /// \brief Specialization of channel_multiply for 8-bit unsigned channels 00424 template<> struct channel_multiplier_unsigned<bits8> : public std::binary_function<bits8,bits8,bits8> { 00425 bits8 operator()(bits8 a, bits8 b) const { return bits8(detail::div255(uint32_t(a) * uint32_t(b))); } 00426 }; 00427 00428 /// \brief Specialization of channel_multiply for 16-bit unsigned channels 00429 template<> struct channel_multiplier_unsigned<bits16> : public std::binary_function<bits16,bits16,bits16> { 00430 bits16 operator()(bits16 a, bits16 b) const { return bits16((uint32_t(a) * uint32_t(b))/65535); } 00431 }; 00432 00433 /// \brief Specialization of channel_multiply for float 0..1 channels 00434 template<> struct channel_multiplier_unsigned<bits32f> : public std::binary_function<bits32f,bits32f,bits32f> { 00435 bits32f operator()(bits32f a, bits32f b) const { return a*b; } 00436 }; 00437 00438 /// \brief A function object to multiply two channels. result = a * b / max_value 00439 template <typename ChannelValue> 00440 struct channel_multiplier : public std::binary_function<ChannelValue, ChannelValue, ChannelValue> { 00441 ChannelValue operator()(ChannelValue a, ChannelValue b) const { 00442 typedef detail::channel_convert_to_unsigned<ChannelValue> to_unsigned; 00443 typedef detail::channel_convert_from_unsigned<ChannelValue> from_unsigned; 00444 typedef channel_multiplier_unsigned<typename to_unsigned::result_type> multiplier_unsigned; 00445 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b))); 00446 } 00447 }; 00448 00449 /// \brief A function multiplying two channels. result = a * b / max_value 00450 template <typename Channel> // Models ChannelConcept (could be a channel reference) 00451 inline typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b) { 00452 return channel_multiplier<typename channel_traits<Channel>::value_type>()(a,b); 00453 } 00454 /// @} 00455 00456 /** 00457 \defgroup ChannelInvertAlgorithm channel_invert 00458 \ingroup ChannelAlgorithm 00459 \brief Returns the inverse of a channel. result = max_value - x + min_value 00460 00461 Example: 00462 \code 00463 // bits8 == uint8_t == unsigned char 00464 bits8 x=255; 00465 bits8 inv = channel_invert(x); 00466 assert(inv == 0); 00467 \endcode 00468 */ 00469 00470 /// \brief Default implementation. Provide overloads for performance 00471 /// \ingroup ChannelInvertAlgorithm channel_invert 00472 template <typename Channel> // Models ChannelConcept (could be a channel reference) 00473 inline typename channel_traits<Channel>::value_type channel_invert(Channel x) { 00474 return channel_traits<Channel>::max_value()-x + channel_traits<Channel>::min_value(); 00475 } 00476 00477 //#ifdef _MSC_VER 00478 //#pragma warning(pop) 00479 //#endif 00480 00481 } } // namespace boost::gil 00482 00483 #endif