Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # 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