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