channel_algorithm.hpp

Go 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  doxygen 1.5.6