Boost GIL


channel_algorithm.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3 
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).
7 
8  See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10 /*************************************************************************************************/
11 
12 #ifndef GIL_CHANNEL_ALGORITHM_HPP
13 #define GIL_CHANNEL_ALGORITHM_HPP
14 
25 
26 #include <boost/config.hpp>
27 #include <boost/mpl/less.hpp>
28 #include <boost/mpl/integral_c.hpp>
29 #include <boost/mpl/greater.hpp>
30 #include <boost/type_traits.hpp>
31 
32 #include "gil_config.hpp"
33 #include "channel.hpp"
34 #include "typedefs.hpp"
35 
36 #include <limits>
37 
38 namespace boost { namespace gil {
39 
40 //#ifdef _MSC_VER
41 //#pragma warning(push)
42 //#pragma warning(disable: 4309) // disable truncation of constant value warning (using -1 to get the max value of an integral)
43 //#endif
44 
45 namespace detail {
46 
47 // some forward declarations
48 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral> struct channel_converter_unsigned_impl;
49 template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater> struct channel_converter_unsigned_integral;
50 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible> struct channel_converter_unsigned_integral_impl;
51 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger> struct channel_converter_unsigned_integral_nondivisible;
52 
56 
57 
58 template <typename UnsignedIntegralChannel>
59 struct unsigned_integral_max_value : public mpl::integral_c<UnsignedIntegralChannel,std::numeric_limits<UnsignedIntegralChannel>::max()> {};
60 
61 template <>
62 struct unsigned_integral_max_value<uint8_t> : public mpl::integral_c<uint32_t,0xFF> {};
63 template <>
64 struct unsigned_integral_max_value<uint16_t> : public mpl::integral_c<uint32_t,0xFFFF> {};
65 template <>
66 struct unsigned_integral_max_value<uint32_t> : public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
67 
68 
69 template <int K>
70 struct unsigned_integral_max_value<packed_channel_value<K> >
71  : public mpl::integral_c<typename packed_channel_value<K>::integer_t, (uint64_t(1)<<K)-1> {};
72 
73 
74 
78 
79 template <typename UnsignedIntegralChannel>
80 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
81 
82 template <int K>
83 struct unsigned_integral_num_bits<packed_channel_value<K> >
84  : public mpl::int_<K> {};
85 
86 } // namespace detail
87 
121 
125 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
126 struct channel_converter_unsigned
127  : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
128 
129 
131 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
132 
133 
134 namespace detail {
135 
139 
141 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
142 struct channel_converter_unsigned_impl {
143  typedef SrcChannelV argument_type;
144  typedef DstChannelV result_type;
145  DstChannelV operator()(SrcChannelV src) const {
146  return DstChannelV(channel_traits<DstChannelV>::min_value() +
147  (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
148  }
149 private:
150  template <typename C>
151  static double channel_range() {
152  return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
153  }
154 };
155 
156 // When both the source and the destination are integral channels, perform a faster conversion
157 template <typename SrcChannelV, typename DstChannelV>
158 struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true>
159  : public channel_converter_unsigned_integral<SrcChannelV,DstChannelV,
160  mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {};
161 
162 
166 
167 template <typename SrcChannelV, typename DstChannelV>
168 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
169  : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
170  !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
171 
172 template <typename SrcChannelV, typename DstChannelV>
173 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
174  : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
175  !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
176 
177 
181 
182 // Both source and destination are unsigned integral channels,
183 // the src max value is less than the dst max value,
184 // and the dst max value is divisible by the src max value
185 template <typename SrcChannelV, typename DstChannelV>
186 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
187  DstChannelV operator()(SrcChannelV src) const {
188  typedef typename unsigned_integral_max_value<DstChannelV>::value_type integer_t;
189  static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
190  return DstChannelV(src * mul);
191  }
192 };
193 
194 // Both source and destination are unsigned integral channels,
195 // the dst max value is less than (or equal to) the src max value,
196 // and the src max value is divisible by the dst max value
197 template <typename SrcChannelV, typename DstChannelV>
198 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
199  DstChannelV operator()(SrcChannelV src) const {
200  typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t;
201  static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
202  static const integer_t div2 = div/2;
203  return DstChannelV((src + div2) / div);
204  }
205 };
206 
207 // Prevent overflow for the largest integral type
208 template <typename DstChannelV>
209 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
210  DstChannelV operator()(uintmax_t src) const {
211  static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
212  static const uintmax_t div2 = div/2;
213  if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
214  return unsigned_integral_max_value<DstChannelV>::value;
215  return DstChannelV((src + div2) / div);
216  }
217 };
218 
219 // Both source and destination are unsigned integral channels,
220 // and the dst max value is not divisible by the src max value
221 // See if you can represent the expression (src * dst_max) / src_max in integral form
222 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
223 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false>
224  : public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,
225  mpl::greater<
226  mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
227  unsigned_integral_num_bits<uintmax_t>
228  >::value> {};
229 
230 
231 // Both source and destination are unsigned integral channels,
232 // the src max value is less than the dst max value,
233 // and the dst max value is not divisible by the src max value
234 // The expression (src * dst_max) / src_max fits in an integer
235 template <typename SrcChannelV, typename DstChannelV>
236 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
237  DstChannelV operator()(SrcChannelV src) const {
238  typedef typename base_channel_type<DstChannelV>::type dest_t;
239  return DstChannelV(static_cast<dest_t>( src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
240  }
241 };
242 
243 // Both source and destination are unsigned integral channels,
244 // the src max value is less than the dst max value,
245 // and the dst max value is not divisible by the src max value
246 // The expression (src * dst_max) / src_max cannot fit in an integer (overflows). Use a double
247 template <typename SrcChannelV, typename DstChannelV>
248 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> {
249  DstChannelV operator()(SrcChannelV src) const {
250  static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value);
251  return DstChannelV(src * mul);
252  }
253 };
254 
255 // Both source and destination are unsigned integral channels,
256 // the dst max value is less than (or equal to) the src max value,
257 // and the src max value is not divisible by the dst max value
258 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
259 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
260  DstChannelV operator()(SrcChannelV src) const {
261 
262  typedef typename detail::unsigned_integral_max_value< SrcChannelV >::value_type src_integer_t;
263  typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
264 
265  static const double div = unsigned_integral_max_value<SrcChannelV>::value
266  / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
267 
268  static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
269 
270  return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
271  }
272 };
273 
274 } // namespace detail
275 
279 
280 template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstChannelV> {
281  typedef float32_t argument_type;
282  typedef DstChannelV result_type;
283  DstChannelV operator()(float32_t x) const
284  {
285  typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
286  return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
287  }
288 };
289 
290 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,float32_t> {
291  typedef float32_t argument_type;
292  typedef SrcChannelV result_type;
293  float32_t operator()(SrcChannelV x) const { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
294 };
295 
296 template <> struct channel_converter_unsigned<float32_t,float32_t> {
297  typedef float32_t argument_type;
298  typedef float32_t result_type;
299  float32_t operator()(float32_t x) const { return x; }
300 };
301 
302 
304 template <> struct channel_converter_unsigned<uint32_t,float32_t> {
305  typedef uint32_t argument_type;
306  typedef float32_t result_type;
307  float32_t operator()(uint32_t x) const {
308  // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of uint32_t matches max_value of float32_t
309  if (x>=channel_traits<uint32_t>::max_value()) return channel_traits<float32_t>::max_value();
310  return float(x) / float(channel_traits<uint32_t>::max_value());
311  }
312 };
314 template <> struct channel_converter_unsigned<float32_t,uint32_t> {
315  typedef float32_t argument_type;
316  typedef uint32_t result_type;
317  uint32_t operator()(float32_t x) const {
318  // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of uint32_t matches max_value of float32_t
321 
322  auto const max_value = channel_traits<uint32_t>::max_value();
323  auto const result = x * static_cast<float32_t::base_channel_t>(max_value) + 0.5f;
324  return static_cast<uint32_t>(result);
325  }
326 };
327 
329 
330 namespace detail {
331 // Converting from signed to unsigned integral channel.
332 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
333 template <typename ChannelValue> // Model ChannelValueConcept
334 struct channel_convert_to_unsigned : public detail::identity<ChannelValue> {
335  typedef ChannelValue type;
336 };
337 
338 template <> struct channel_convert_to_unsigned<int8_t> {
339  typedef int8_t argument_type;
340  typedef uint8_t result_type;
341  typedef uint8_t type;
342  type operator()(int8_t val) const {
343  return static_cast<uint8_t>(static_cast<uint32_t>(val) + 128u);
344  }
345 };
346 
347 template <> struct channel_convert_to_unsigned<int16_t> {
348  typedef int16_t argument_type;
349  typedef uint16_t result_type;
350  typedef uint16_t type;
351  type operator()(int16_t val) const {
352  return static_cast<uint16_t>(static_cast<uint32_t>(val) + 32768u);
353  }
354 };
355 
356 template <> struct channel_convert_to_unsigned<int32_t> {
357  typedef int32_t argument_type;
358  typedef uint32_t result_type;
359  typedef uint32_t type;
360  type operator()(int32_t val) const {
361  return static_cast<uint32_t>(val)+(1u<<31);
362  }
363 };
364 
365 
366 // Converting from unsigned to signed integral channel
367 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
368 template <typename ChannelValue> // Model ChannelValueConcept
369 struct channel_convert_from_unsigned : public detail::identity<ChannelValue> {
370  typedef ChannelValue type;
371 };
372 
373 template <> struct channel_convert_from_unsigned<int8_t> {
374  typedef uint8_t argument_type;
375  typedef int8_t result_type;
376  typedef int8_t type;
377  type operator()(uint8_t val) const {
378  return static_cast<int8_t>(static_cast<int32_t>(val) - 128);
379  }
380 };
381 
382 template <> struct channel_convert_from_unsigned<int16_t> {
383  typedef uint16_t argument_type;
384  typedef int16_t result_type;
385  typedef int16_t type;
386  type operator()(uint16_t val) const {
387  return static_cast<int16_t>(static_cast<int32_t>(val) - 32768);
388  }
389 };
390 
391 template <> struct channel_convert_from_unsigned<int32_t> {
392  typedef uint32_t argument_type;
393  typedef int32_t result_type;
394  typedef int32_t type;
395  type operator()(uint32_t val) const {
396  return static_cast<int32_t>(val - (1u<<31));
397  }
398 };
399 
400 } // namespace detail
401 
404 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
406  typedef SrcChannelV argument_type;
407  typedef DstChannelV result_type;
408  DstChannelV operator()(const SrcChannelV& src) const {
409  typedef detail::channel_convert_to_unsigned<SrcChannelV> to_unsigned;
410  typedef detail::channel_convert_from_unsigned<DstChannelV> from_unsigned;
411  typedef channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type> converter_unsigned;
412  return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
413  }
414 };
415 
418 template <typename DstChannel, typename SrcChannel> // Model ChannelConcept (could be channel references)
419 inline typename channel_traits<DstChannel>::value_type channel_convert(const SrcChannel& src) {
421  typename channel_traits<DstChannel>::value_type>()(src);
422 }
423 
429  template <typename Ch1, typename Ch2>
430  void operator()(const Ch1& src, Ch2& dst) const {
431  dst=channel_convert<Ch2>(src);
432  }
433 };
434 
435 namespace detail {
436  // fast integer division by 255
437  inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; }
438 
439  // fast integer divison by 32768
440  inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; }
441 }
442 
456 
459 template <typename ChannelValue>
461  typedef ChannelValue first_argument_type;
462  typedef ChannelValue second_argument_type;
463  typedef ChannelValue result_type;
464  ChannelValue operator()(ChannelValue a, ChannelValue b) const {
465  return ChannelValue(static_cast<typename base_channel_type<ChannelValue>::type>(a / double(channel_traits<ChannelValue>::max_value()) * b));
466  }
467 };
468 
470 template<> struct channel_multiplier_unsigned<uint8_t> {
471  typedef uint8_t first_argument_type;
472  typedef uint8_t second_argument_type;
473  typedef uint8_t result_type;
474  uint8_t operator()(uint8_t a, uint8_t b) const { return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
475 };
476 
478 template<> struct channel_multiplier_unsigned<uint16_t> {
479  typedef uint16_t first_argument_type;
480  typedef uint16_t second_argument_type;
481  typedef uint16_t result_type;
482  uint16_t operator()(uint16_t a, uint16_t b) const { return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
483 };
484 
489  typedef float32_t result_type;
490  float32_t operator()(float32_t a, float32_t b) const { return a*b; }
491 };
492 
494 template <typename ChannelValue>
496  typedef ChannelValue first_argument_type;
497  typedef ChannelValue second_argument_type;
498  typedef ChannelValue result_type;
499  ChannelValue operator()(ChannelValue a, ChannelValue b) const {
500  typedef detail::channel_convert_to_unsigned<ChannelValue> to_unsigned;
501  typedef detail::channel_convert_from_unsigned<ChannelValue> from_unsigned;
503  return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
504  }
505 };
506 
508 template <typename Channel> // Models ChannelConcept (could be a channel reference)
509 inline typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b) {
511 }
513 
528 template <typename Channel> // Models ChannelConcept (could be a channel reference)
533 }
534 
535 //#ifdef _MSC_VER
536 //#pragma warning(pop)
537 //#endif
538 
539 } } // namespace boost::gil
540 
541 #endif
channel_traits< Channel >::value_type channel_invert(Channel x)
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:531
A channel adaptor that modifies the range of the source channel. Models: ChannelValueConcept.
Definition: channel.hpp:156
channel_traits< DstChannel >::value_type channel_convert(const SrcChannel &src)
Converting from one channel type to another.
Definition: channel_algorithm.hpp:419
Channel utilities.
channel_traits< Channel >::value_type channel_multiply(Channel a, Channel b)
A function multiplying two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:509
identity taken from SGI STL.
Definition: utilities.hpp:265
Same as channel_converter, except it takes the destination channel by reference, which allows us to m...
Definition: channel_algorithm.hpp:428
A function object to multiply two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:495
Useful public typedefs.
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:460
Traits for channels. Contains the following members:
Definition: channel.hpp:114
GIL configuration file.
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:48
A unary function object converting between channel types.
Definition: channel_algorithm.hpp:405