annotate DEPENDENCIES/generic/include/boost/gil/channel_algorithm.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /*
Chris@16 2 Copyright 2005-2007 Adobe Systems Incorporated
Chris@16 3
Chris@16 4 Use, modification and distribution are subject to the Boost Software License,
Chris@16 5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 http://www.boost.org/LICENSE_1_0.txt).
Chris@16 7
Chris@16 8 See http://opensource.adobe.com/gil for most recent version including documentation.
Chris@16 9 */
Chris@16 10 /*************************************************************************************************/
Chris@16 11
Chris@16 12 #ifndef GIL_CHANNEL_ALGORITHM_HPP
Chris@16 13 #define GIL_CHANNEL_ALGORITHM_HPP
Chris@16 14
Chris@16 15 ////////////////////////////////////////////////////////////////////////////////////////
Chris@16 16 /// \file
Chris@16 17 /// \brief Channel algorithms
Chris@16 18 /// \author Lubomir Bourdev and Hailin Jin \n
Chris@16 19 /// Adobe Systems Incorporated
Chris@16 20 /// \date 2005-2007 \n Last updated on May 6, 2007
Chris@16 21 ///
Chris@16 22 /// Definitions of standard GIL 8-bit, 16-bit, 32-bit channels
Chris@16 23 ///
Chris@16 24 ////////////////////////////////////////////////////////////////////////////////////////
Chris@16 25
Chris@16 26 #include "gil_config.hpp"
Chris@16 27 #include "channel.hpp"
Chris@16 28 #include <boost/mpl/less.hpp>
Chris@16 29 #include <boost/mpl/integral_c.hpp>
Chris@16 30 #include <boost/mpl/greater.hpp>
Chris@16 31 #include <boost/type_traits.hpp>
Chris@16 32
Chris@16 33 namespace boost { namespace gil {
Chris@16 34
Chris@16 35 //#ifdef _MSC_VER
Chris@16 36 //#pragma warning(push)
Chris@16 37 //#pragma warning(disable: 4309) // disable truncation of constant value warning (using -1 to get the max value of an integral)
Chris@16 38 //#endif
Chris@16 39
Chris@16 40 namespace detail {
Chris@16 41
Chris@16 42 // some forward declarations
Chris@16 43 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral> struct channel_converter_unsigned_impl;
Chris@16 44 template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater> struct channel_converter_unsigned_integral;
Chris@16 45 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible> struct channel_converter_unsigned_integral_impl;
Chris@16 46 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger> struct channel_converter_unsigned_integral_nondivisible;
Chris@16 47
Chris@16 48 //////////////////////////////////////
Chris@16 49 //// unsigned_integral_max_value - given an unsigned integral channel type, returns its maximum value as an MPL integral constant
Chris@16 50 //////////////////////////////////////
Chris@16 51
Chris@16 52
Chris@16 53 template <typename UnsignedIntegralChannel>
Chris@16 54 struct unsigned_integral_max_value : public mpl::integral_c<UnsignedIntegralChannel,-1> {};
Chris@16 55
Chris@16 56 template <>
Chris@16 57 struct unsigned_integral_max_value<uint8_t> : public mpl::integral_c<uint32_t,0xFF> {};
Chris@16 58 template <>
Chris@16 59 struct unsigned_integral_max_value<uint16_t> : public mpl::integral_c<uint32_t,0xFFFF> {};
Chris@16 60 template <>
Chris@16 61 struct unsigned_integral_max_value<uint32_t> : public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
Chris@16 62
Chris@16 63
Chris@16 64 template <int K>
Chris@16 65 struct unsigned_integral_max_value<packed_channel_value<K> >
Chris@16 66 : public mpl::integral_c<typename packed_channel_value<K>::integer_t, (1<<K)-1> {};
Chris@16 67
Chris@16 68 //////////////////////////////////////
Chris@16 69 //// unsigned_integral_num_bits - given an unsigned integral channel type, returns the minimum number of bits needed to represent it
Chris@16 70 //////////////////////////////////////
Chris@16 71
Chris@16 72 template <typename UnsignedIntegralChannel>
Chris@16 73 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
Chris@16 74
Chris@16 75 template <int K>
Chris@16 76 struct unsigned_integral_num_bits<packed_channel_value<K> >
Chris@16 77 : public mpl::int_<K> {};
Chris@16 78
Chris@16 79 } // namespace detail
Chris@16 80
Chris@16 81 /**
Chris@16 82 \defgroup ChannelConvertAlgorithm channel_convert
Chris@16 83 \brief Converting from one channel type to another
Chris@16 84 \ingroup ChannelAlgorithm
Chris@16 85
Chris@16 86 Conversion is done as a simple linear mapping of one channel range to the other,
Chris@16 87 such that the minimum/maximum value of the source maps to the minimum/maximum value of the destination.
Chris@16 88 One implication of this is that the value 0 of signed channels may not be preserved!
Chris@16 89
Chris@16 90 When creating new channel models, it is often a good idea to provide specializations for the channel conversion algorithms, for
Chris@16 91 example, for performance optimizations. If the new model is an integral type that can be signed, it is easier to define the conversion
Chris@16 92 only for the unsigned type (\p channel_converter_unsigned) and provide specializations of \p detail::channel_convert_to_unsigned
Chris@16 93 and \p detail::channel_convert_from_unsigned to convert between the signed and unsigned type.
Chris@16 94
Chris@16 95 Example:
Chris@16 96 \code
Chris@16 97 // bits32f is a floating point channel with range [0.0f ... 1.0f]
Chris@16 98 bits32f src_channel = channel_traits<bits32f>::max_value();
Chris@16 99 assert(src_channel == 1);
Chris@16 100
Chris@16 101 // bits8 is 8-bit unsigned integral channel (typedef-ed from unsigned char)
Chris@16 102 bits8 dst_channel = channel_convert<bits8>(src_channel);
Chris@16 103 assert(dst_channel == 255); // max value goes to max value
Chris@16 104 \endcode
Chris@16 105 */
Chris@16 106
Chris@16 107 /**
Chris@16 108 \defgroup ChannelConvertUnsignedAlgorithm channel_converter_unsigned
Chris@16 109 \ingroup ChannelConvertAlgorithm
Chris@16 110 \brief Convert one unsigned/floating point channel to another. Converts both the channel type and range
Chris@16 111 @{
Chris@16 112 */
Chris@16 113
Chris@16 114 //////////////////////////////////////
Chris@16 115 //// channel_converter_unsigned
Chris@16 116 //////////////////////////////////////
Chris@16 117
Chris@16 118 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
Chris@16 119 struct channel_converter_unsigned
Chris@16 120 : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
Chris@16 121
Chris@16 122
Chris@16 123 /// \brief Converting a channel to itself - identity operation
Chris@16 124 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
Chris@16 125
Chris@16 126
Chris@16 127 namespace detail {
Chris@16 128
Chris@16 129 //////////////////////////////////////
Chris@16 130 //// channel_converter_unsigned_impl
Chris@16 131 //////////////////////////////////////
Chris@16 132
Chris@16 133 /// \brief This is the default implementation. Performance specializatons are provided
Chris@16 134 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
Chris@16 135 struct channel_converter_unsigned_impl : public std::unary_function<DstChannelV,SrcChannelV> {
Chris@16 136 DstChannelV operator()(SrcChannelV src) const {
Chris@16 137 return DstChannelV(channel_traits<DstChannelV>::min_value() +
Chris@16 138 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
Chris@16 139 }
Chris@16 140 private:
Chris@16 141 template <typename C>
Chris@16 142 static double channel_range() {
Chris@16 143 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
Chris@16 144 }
Chris@16 145 };
Chris@16 146
Chris@16 147 // When both the source and the destination are integral channels, perform a faster conversion
Chris@16 148 template <typename SrcChannelV, typename DstChannelV>
Chris@16 149 struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true>
Chris@16 150 : public channel_converter_unsigned_integral<SrcChannelV,DstChannelV,
Chris@16 151 mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {};
Chris@16 152
Chris@16 153
Chris@16 154 //////////////////////////////////////
Chris@16 155 //// channel_converter_unsigned_integral
Chris@16 156 //////////////////////////////////////
Chris@16 157
Chris@16 158 template <typename SrcChannelV, typename DstChannelV>
Chris@16 159 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
Chris@16 160 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
Chris@16 161 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
Chris@16 162
Chris@16 163 template <typename SrcChannelV, typename DstChannelV>
Chris@16 164 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
Chris@16 165 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
Chris@16 166 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
Chris@16 167
Chris@16 168
Chris@16 169 //////////////////////////////////////
Chris@16 170 //// channel_converter_unsigned_integral_impl
Chris@16 171 //////////////////////////////////////
Chris@16 172
Chris@16 173 // Both source and destination are unsigned integral channels,
Chris@16 174 // the src max value is less than the dst max value,
Chris@16 175 // and the dst max value is divisible by the src max value
Chris@16 176 template <typename SrcChannelV, typename DstChannelV>
Chris@16 177 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
Chris@16 178 DstChannelV operator()(SrcChannelV src) const {
Chris@16 179 typedef typename unsigned_integral_max_value<DstChannelV>::value_type integer_t;
Chris@16 180 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
Chris@16 181 return DstChannelV(src * mul);
Chris@16 182 }
Chris@16 183 };
Chris@16 184
Chris@16 185 // Both source and destination are unsigned integral channels,
Chris@16 186 // the dst max value is less than (or equal to) the src max value,
Chris@16 187 // and the src max value is divisible by the dst max value
Chris@16 188 template <typename SrcChannelV, typename DstChannelV>
Chris@16 189 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
Chris@16 190 DstChannelV operator()(SrcChannelV src) const {
Chris@16 191 typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t;
Chris@16 192 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
Chris@16 193 static const integer_t div2 = div/2;
Chris@16 194 return DstChannelV((src + div2) / div);
Chris@16 195 }
Chris@16 196 };
Chris@16 197
Chris@16 198 // Prevent overflow for the largest integral type
Chris@16 199 template <typename DstChannelV>
Chris@16 200 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
Chris@16 201 DstChannelV operator()(uintmax_t src) const {
Chris@16 202 static const uintmax_t div = unsigned_integral_max_value<bits32>::value / unsigned_integral_max_value<DstChannelV>::value;
Chris@16 203 static const uintmax_t div2 = div/2;
Chris@16 204 if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
Chris@16 205 return unsigned_integral_max_value<DstChannelV>::value;
Chris@16 206 return DstChannelV((src + div2) / div);
Chris@16 207 }
Chris@16 208 };
Chris@16 209
Chris@16 210 // Both source and destination are unsigned integral channels,
Chris@16 211 // and the dst max value is not divisible by the src max value
Chris@16 212 // See if you can represent the expression (src * dst_max) / src_max in integral form
Chris@16 213 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
Chris@16 214 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false>
Chris@16 215 : public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,
Chris@16 216 mpl::greater<
Chris@16 217 mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
Chris@16 218 unsigned_integral_num_bits<uintmax_t>
Chris@16 219 >::value> {};
Chris@16 220
Chris@16 221
Chris@16 222 // Both source and destination are unsigned integral channels,
Chris@16 223 // the src max value is less than the dst max value,
Chris@16 224 // and the dst max value is not divisible by the src max value
Chris@16 225 // The expression (src * dst_max) / src_max fits in an integer
Chris@16 226 template <typename SrcChannelV, typename DstChannelV>
Chris@16 227 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
Chris@16 228 DstChannelV operator()(SrcChannelV src) const {
Chris@16 229 typedef typename detail::min_fast_uint<unsigned_integral_num_bits<SrcChannelV>::value+unsigned_integral_num_bits<DstChannelV>::value>::type integer_t;
Chris@16 230 return DstChannelV(integer_t(src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
Chris@16 231 }
Chris@16 232 };
Chris@16 233
Chris@16 234 // Both source and destination are unsigned integral channels,
Chris@16 235 // the src max value is less than the dst max value,
Chris@16 236 // and the dst max value is not divisible by the src max value
Chris@16 237 // The expression (src * dst_max) / src_max cannot fit in an integer (overflows). Use a double
Chris@16 238 template <typename SrcChannelV, typename DstChannelV>
Chris@16 239 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> {
Chris@16 240 DstChannelV operator()(SrcChannelV src) const {
Chris@16 241 static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value);
Chris@16 242 return DstChannelV(src * mul);
Chris@16 243 }
Chris@16 244 };
Chris@16 245
Chris@16 246 // Both source and destination are unsigned integral channels,
Chris@16 247 // the dst max value is less than (or equal to) the src max value,
Chris@16 248 // and the src max value is not divisible by the dst max value
Chris@16 249 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
Chris@16 250 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
Chris@16 251 DstChannelV operator()(SrcChannelV src) const {
Chris@16 252
Chris@16 253 typedef typename detail::unsigned_integral_max_value< SrcChannelV >::value_type src_integer_t;
Chris@16 254 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
Chris@16 255
Chris@16 256 static const double div = unsigned_integral_max_value<SrcChannelV>::value
Chris@16 257 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
Chris@16 258
Chris@16 259 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
Chris@16 260
Chris@16 261 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
Chris@16 262 }
Chris@16 263 };
Chris@16 264
Chris@16 265 } // namespace detail
Chris@16 266
Chris@16 267 /////////////////////////////////////////////////////
Chris@16 268 /// bits32f conversion
Chris@16 269 /////////////////////////////////////////////////////
Chris@16 270
Chris@16 271 template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> {
Chris@16 272 DstChannelV operator()(bits32f x) const
Chris@16 273 {
Chris@16 274 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
Chris@16 275 return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
Chris@16 276 }
Chris@16 277 };
Chris@16 278
Chris@16 279 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> {
Chris@16 280 bits32f operator()(SrcChannelV x) const { return bits32f(x/float(channel_traits<SrcChannelV>::max_value())); }
Chris@16 281 };
Chris@16 282
Chris@16 283 template <> struct channel_converter_unsigned<bits32f,bits32f> : public std::unary_function<bits32f,bits32f> {
Chris@16 284 bits32f operator()(bits32f x) const { return x; }
Chris@16 285 };
Chris@16 286
Chris@16 287
Chris@16 288 /// \brief 32 bit <-> float channel conversion
Chris@16 289 template <> struct channel_converter_unsigned<bits32,bits32f> : public std::unary_function<bits32,bits32f> {
Chris@16 290 bits32f operator()(bits32 x) const {
Chris@16 291 // 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
Chris@16 292 if (x>=channel_traits<bits32>::max_value()) return channel_traits<bits32f>::max_value();
Chris@16 293 return float(x) / float(channel_traits<bits32>::max_value());
Chris@16 294 }
Chris@16 295 };
Chris@16 296 /// \brief 32 bit <-> float channel conversion
Chris@16 297 template <> struct channel_converter_unsigned<bits32f,bits32> : public std::unary_function<bits32f,bits32> {
Chris@16 298 bits32 operator()(bits32f x) const {
Chris@16 299 // 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
Chris@16 300 if (x>=channel_traits<bits32f>::max_value()) return channel_traits<bits32>::max_value();
Chris@16 301 return bits32(x * channel_traits<bits32>::max_value() + 0.5f);
Chris@16 302 }
Chris@16 303 };
Chris@16 304
Chris@16 305 /// @}
Chris@16 306
Chris@16 307 namespace detail {
Chris@16 308 // Converting from signed to unsigned integral channel.
Chris@16 309 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
Chris@16 310 template <typename ChannelValue> // Model ChannelValueConcept
Chris@16 311 struct channel_convert_to_unsigned : public detail::identity<ChannelValue> {
Chris@16 312 typedef ChannelValue type;
Chris@16 313 };
Chris@16 314
Chris@16 315 template <> struct channel_convert_to_unsigned<bits8s> : public std::unary_function<bits8s,bits8> {
Chris@16 316 typedef bits8 type;
Chris@16 317 type operator()(bits8s val) const { return val+128; }
Chris@16 318 };
Chris@16 319
Chris@16 320 template <> struct channel_convert_to_unsigned<bits16s> : public std::unary_function<bits16s,bits16> {
Chris@16 321 typedef bits16 type;
Chris@16 322 type operator()(bits16s val) const { return val+32768; }
Chris@16 323 };
Chris@16 324
Chris@16 325 template <> struct channel_convert_to_unsigned<bits32s> : public std::unary_function<bits32s,bits32> {
Chris@16 326 typedef bits32 type;
Chris@16 327 type operator()(bits32s x) const { return static_cast<bits32>(x+(1<<31)); }
Chris@16 328 };
Chris@16 329
Chris@16 330
Chris@16 331 // Converting from unsigned to signed integral channel
Chris@16 332 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
Chris@16 333 template <typename ChannelValue> // Model ChannelValueConcept
Chris@16 334 struct channel_convert_from_unsigned : public detail::identity<ChannelValue> {
Chris@16 335 typedef ChannelValue type;
Chris@16 336 };
Chris@16 337
Chris@16 338 template <> struct channel_convert_from_unsigned<bits8s> : public std::unary_function<bits8,bits8s> {
Chris@16 339 typedef bits8s type;
Chris@16 340 type operator()(bits8 val) const { return val-128; }
Chris@16 341 };
Chris@16 342
Chris@16 343 template <> struct channel_convert_from_unsigned<bits16s> : public std::unary_function<bits16,bits16s> {
Chris@16 344 typedef bits16s type;
Chris@16 345 type operator()(bits16 val) const { return val-32768; }
Chris@16 346 };
Chris@16 347
Chris@16 348 template <> struct channel_convert_from_unsigned<bits32s> : public std::unary_function<bits32,bits32s> {
Chris@16 349 typedef bits32s type;
Chris@16 350 type operator()(bits32 x) const { return static_cast<bits32s>(x-(1<<31)); }
Chris@16 351 };
Chris@16 352
Chris@16 353 } // namespace detail
Chris@16 354
Chris@16 355 /// \ingroup ChannelConvertAlgorithm
Chris@16 356 /// \brief A unary function object converting between channel types
Chris@16 357 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
Chris@16 358 struct channel_converter : public std::unary_function<SrcChannelV,DstChannelV> {
Chris@16 359 DstChannelV operator()(const SrcChannelV& src) const {
Chris@16 360 typedef detail::channel_convert_to_unsigned<SrcChannelV> to_unsigned;
Chris@16 361 typedef detail::channel_convert_from_unsigned<DstChannelV> from_unsigned;
Chris@16 362 typedef channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type> converter_unsigned;
Chris@16 363 return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
Chris@16 364 }
Chris@16 365 };
Chris@16 366
Chris@16 367 /// \ingroup ChannelConvertAlgorithm
Chris@16 368 /// \brief Converting from one channel type to another.
Chris@16 369 template <typename DstChannel, typename SrcChannel> // Model ChannelConcept (could be channel references)
Chris@16 370 inline typename channel_traits<DstChannel>::value_type channel_convert(const SrcChannel& src) {
Chris@16 371 return channel_converter<typename channel_traits<SrcChannel>::value_type,
Chris@16 372 typename channel_traits<DstChannel>::value_type>()(src);
Chris@16 373 }
Chris@16 374
Chris@16 375 /// \ingroup ChannelConvertAlgorithm
Chris@16 376 /// \brief Same as channel_converter, except it takes the destination channel by reference, which allows
Chris@16 377 /// us to move the templates from the class level to the method level. This is important when invoking it
Chris@16 378 /// on heterogeneous pixels.
Chris@16 379 struct default_channel_converter {
Chris@16 380 template <typename Ch1, typename Ch2>
Chris@16 381 void operator()(const Ch1& src, Ch2& dst) const {
Chris@16 382 dst=channel_convert<Ch2>(src);
Chris@16 383 }
Chris@16 384 };
Chris@16 385
Chris@16 386 namespace detail {
Chris@16 387 // fast integer division by 255
Chris@16 388 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; }
Chris@16 389
Chris@16 390 // fast integer divison by 32768
Chris@16 391 inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; }
Chris@16 392 }
Chris@16 393
Chris@16 394 /**
Chris@16 395 \defgroup ChannelMultiplyAlgorithm channel_multiply
Chris@16 396 \ingroup ChannelAlgorithm
Chris@16 397 \brief Multiplying unsigned channel values of the same type. Performs scaled multiplication result = a * b / max_value
Chris@16 398
Chris@16 399 Example:
Chris@16 400 \code
Chris@16 401 bits8 x=128;
Chris@16 402 bits8 y=128;
Chris@16 403 bits8 mul = channel_multiply(x,y);
Chris@16 404 assert(mul == 64); // 64 = 128 * 128 / 255
Chris@16 405 \endcode
Chris@16 406 */
Chris@16 407 /// @{
Chris@16 408
Chris@16 409 /// \brief This is the default implementation. Performance specializatons are provided
Chris@16 410 template <typename ChannelValue>
Chris@16 411 struct channel_multiplier_unsigned : public std::binary_function<ChannelValue,ChannelValue,ChannelValue> {
Chris@16 412 ChannelValue operator()(ChannelValue a, ChannelValue b) const {
Chris@16 413 return ChannelValue(a / double(channel_traits<ChannelValue>::max_value()) * b);
Chris@16 414 }
Chris@16 415 };
Chris@16 416
Chris@16 417 /// \brief Specialization of channel_multiply for 8-bit unsigned channels
Chris@16 418 template<> struct channel_multiplier_unsigned<bits8> : public std::binary_function<bits8,bits8,bits8> {
Chris@16 419 bits8 operator()(bits8 a, bits8 b) const { return bits8(detail::div255(uint32_t(a) * uint32_t(b))); }
Chris@16 420 };
Chris@16 421
Chris@16 422 /// \brief Specialization of channel_multiply for 16-bit unsigned channels
Chris@16 423 template<> struct channel_multiplier_unsigned<bits16> : public std::binary_function<bits16,bits16,bits16> {
Chris@16 424 bits16 operator()(bits16 a, bits16 b) const { return bits16((uint32_t(a) * uint32_t(b))/65535); }
Chris@16 425 };
Chris@16 426
Chris@16 427 /// \brief Specialization of channel_multiply for float 0..1 channels
Chris@16 428 template<> struct channel_multiplier_unsigned<bits32f> : public std::binary_function<bits32f,bits32f,bits32f> {
Chris@16 429 bits32f operator()(bits32f a, bits32f b) const { return a*b; }
Chris@16 430 };
Chris@16 431
Chris@16 432 /// \brief A function object to multiply two channels. result = a * b / max_value
Chris@16 433 template <typename ChannelValue>
Chris@16 434 struct channel_multiplier : public std::binary_function<ChannelValue, ChannelValue, ChannelValue> {
Chris@16 435 ChannelValue operator()(ChannelValue a, ChannelValue b) const {
Chris@16 436 typedef detail::channel_convert_to_unsigned<ChannelValue> to_unsigned;
Chris@16 437 typedef detail::channel_convert_from_unsigned<ChannelValue> from_unsigned;
Chris@16 438 typedef channel_multiplier_unsigned<typename to_unsigned::result_type> multiplier_unsigned;
Chris@16 439 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
Chris@16 440 }
Chris@16 441 };
Chris@16 442
Chris@16 443 /// \brief A function multiplying two channels. result = a * b / max_value
Chris@16 444 template <typename Channel> // Models ChannelConcept (could be a channel reference)
Chris@16 445 inline typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b) {
Chris@16 446 return channel_multiplier<typename channel_traits<Channel>::value_type>()(a,b);
Chris@16 447 }
Chris@16 448 /// @}
Chris@16 449
Chris@16 450 /**
Chris@16 451 \defgroup ChannelInvertAlgorithm channel_invert
Chris@16 452 \ingroup ChannelAlgorithm
Chris@16 453 \brief Returns the inverse of a channel. result = max_value - x + min_value
Chris@16 454
Chris@16 455 Example:
Chris@16 456 \code
Chris@16 457 // bits8 == uint8_t == unsigned char
Chris@16 458 bits8 x=255;
Chris@16 459 bits8 inv = channel_invert(x);
Chris@16 460 assert(inv == 0);
Chris@16 461 \endcode
Chris@16 462 */
Chris@16 463
Chris@16 464 /// \brief Default implementation. Provide overloads for performance
Chris@16 465 /// \ingroup ChannelInvertAlgorithm channel_invert
Chris@16 466 template <typename Channel> // Models ChannelConcept (could be a channel reference)
Chris@16 467 inline typename channel_traits<Channel>::value_type channel_invert(Channel x) {
Chris@16 468 return channel_traits<Channel>::max_value()-x + channel_traits<Channel>::min_value();
Chris@16 469 }
Chris@16 470
Chris@16 471 //#ifdef _MSC_VER
Chris@16 472 //#pragma warning(pop)
Chris@16 473 //#endif
Chris@16 474
Chris@16 475 } } // namespace boost::gil
Chris@16 476
Chris@16 477 #endif