00001
00002
00003
00004
00005
00006
00007
00008
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
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 }
00080
00114
00115
00116
00117
00118 template <typename SrcChannelV, typename DstChannelV>
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
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
00174
00175
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
00186
00187
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
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
00211
00212
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
00223
00224
00225
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
00235
00236
00237
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
00248
00249
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 }
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
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
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
00301
00302 template <typename ChannelValue>
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
00324
00325 template <typename ChannelValue>
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 }
00346
00349 template <typename SrcChannelV, typename DstChannelV>
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>
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
00380 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; }
00381
00382
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>
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>
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 } }
00468
00469 #endif