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/integer_traits.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>
32 
33 #include "gil_config.hpp"
34 #include "channel.hpp"
35 
36 namespace boost { namespace gil {
37 
38 //#ifdef _MSC_VER
39 //#pragma warning(push)
40 //#pragma warning(disable: 4309) // disable truncation of constant value warning (using -1 to get the max value of an integral)
41 //#endif
42 
43 namespace detail {
44 
45 // some forward declarations
46 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral> struct channel_converter_unsigned_impl;
47 template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater> struct channel_converter_unsigned_integral;
48 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible> struct channel_converter_unsigned_integral_impl;
49 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger> struct channel_converter_unsigned_integral_nondivisible;
50 
54 
55 
56 template <typename UnsignedIntegralChannel>
57 struct unsigned_integral_max_value : public mpl::integral_c<UnsignedIntegralChannel,integer_traits< UnsignedIntegralChannel>::const_max> {};
58 
59 template <>
60 struct unsigned_integral_max_value<uint8_t> : public mpl::integral_c<uint32_t,0xFF> {};
61 template <>
62 struct unsigned_integral_max_value<uint16_t> : public mpl::integral_c<uint32_t,0xFFFF> {};
63 template <>
64 struct unsigned_integral_max_value<uint32_t> : public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
65 
66 
67 template <int K>
68 struct unsigned_integral_max_value<packed_channel_value<K> >
69  : public mpl::integral_c<typename packed_channel_value<K>::integer_t, (uint64_t(1)<<K)-1> {};
70 
71 
72 
76 
77 template <typename UnsignedIntegralChannel>
78 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
79 
80 template <int K>
81 struct unsigned_integral_num_bits<packed_channel_value<K> >
82  : public mpl::int_<K> {};
83 
84 } // namespace detail
85 
119 
123 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
124 struct channel_converter_unsigned
125  : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
126 
127 
129 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
130 
131 
132 namespace detail {
133 
137 
139 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
140 struct channel_converter_unsigned_impl {
141  typedef SrcChannelV argument_type;
142  typedef DstChannelV result_type;
143  DstChannelV operator()(SrcChannelV src) const {
144  return DstChannelV(channel_traits<DstChannelV>::min_value() +
145  (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
146  }
147 private:
148  template <typename C>
149  static double channel_range() {
150  return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
151  }
152 };
153 
154 // When both the source and the destination are integral channels, perform a faster conversion
155 template <typename SrcChannelV, typename DstChannelV>
156 struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true>
157  : public channel_converter_unsigned_integral<SrcChannelV,DstChannelV,
158  mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {};
159 
160 
164 
165 template <typename SrcChannelV, typename DstChannelV>
166 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
167  : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
168  !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
169 
170 template <typename SrcChannelV, typename DstChannelV>
171 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
172  : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
173  !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
174 
175 
179 
180 // Both source and destination are unsigned integral channels,
181 // the src max value is less than the dst max value,
182 // and the dst max value is divisible by the src max value
183 template <typename SrcChannelV, typename DstChannelV>
184 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
185  DstChannelV operator()(SrcChannelV src) const {
186  typedef typename unsigned_integral_max_value<DstChannelV>::value_type integer_t;
187  static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
188  return DstChannelV(src * mul);
189  }
190 };
191 
192 // Both source and destination are unsigned integral channels,
193 // the dst max value is less than (or equal to) the src max value,
194 // and the src max value is divisible by the dst max value
195 template <typename SrcChannelV, typename DstChannelV>
196 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
197  DstChannelV operator()(SrcChannelV src) const {
198  typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t;
199  static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
200  static const integer_t div2 = div/2;
201  return DstChannelV((src + div2) / div);
202  }
203 };
204 
205 // Prevent overflow for the largest integral type
206 template <typename DstChannelV>
207 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
208  DstChannelV operator()(uintmax_t src) const {
209  static const uintmax_t div = unsigned_integral_max_value<bits32>::value / unsigned_integral_max_value<DstChannelV>::value;
210  static const uintmax_t div2 = div/2;
211  if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
212  return unsigned_integral_max_value<DstChannelV>::value;
213  return DstChannelV((src + div2) / div);
214  }
215 };
216 
217 // Both source and destination are unsigned integral channels,
218 // and the dst max value is not divisible by the src max value
219 // See if you can represent the expression (src * dst_max) / src_max in integral form
220 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
221 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false>
222  : public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,
223  mpl::greater<
224  mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
225  unsigned_integral_num_bits<uintmax_t>
226  >::value> {};
227 
228 
229 // Both source and destination are unsigned integral channels,
230 // the src max value is less than the dst max value,
231 // and the dst max value is not divisible by the src max value
232 // The expression (src * dst_max) / src_max fits in an integer
233 template <typename SrcChannelV, typename DstChannelV>
234 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
235  DstChannelV operator()(SrcChannelV src) const {
236  typedef typename base_channel_type<DstChannelV>::type dest_t;
237  return DstChannelV(static_cast<dest_t>( src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
238  }
239 };
240 
241 // Both source and destination are unsigned integral channels,
242 // the src max value is less than the dst max value,
243 // and the dst max value is not divisible by the src max value
244 // The expression (src * dst_max) / src_max cannot fit in an integer (overflows). Use a double
245 template <typename SrcChannelV, typename DstChannelV>
246 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> {
247  DstChannelV operator()(SrcChannelV src) const {
248  static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value);
249  return DstChannelV(src * mul);
250  }
251 };
252 
253 // Both source and destination are unsigned integral channels,
254 // the dst max value is less than (or equal to) the src max value,
255 // and the src max value is not divisible by the dst max value
256 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
257 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
258  DstChannelV operator()(SrcChannelV src) const {
259 
260  typedef typename detail::unsigned_integral_max_value< SrcChannelV >::value_type src_integer_t;
261  typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
262 
263  static const double div = unsigned_integral_max_value<SrcChannelV>::value
264  / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
265 
266  static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
267 
268  return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
269  }
270 };
271 
272 } // namespace detail
273 
277 
278 template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> {
279  typedef bits32f argument_type;
280  typedef DstChannelV result_type;
281  DstChannelV operator()(bits32f x) const
282  {
283  typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
284  return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
285  }
286 };
287 
288 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> {
289  typedef bits32f argument_type;
290  typedef SrcChannelV result_type;
291  bits32f operator()(SrcChannelV x) const { return bits32f(x/float(channel_traits<SrcChannelV>::max_value())); }
292 };
293 
294 template <> struct channel_converter_unsigned<bits32f,bits32f> {
295  typedef bits32f argument_type;
296  typedef bits32f result_type;
297  bits32f operator()(bits32f x) const { return x; }
298 };
299 
300 
302 template <> struct channel_converter_unsigned<bits32,bits32f> {
303  typedef bits32 argument_type;
304  typedef bits32f result_type;
305  bits32f operator()(bits32 x) const {
306  // 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
307  if (x>=channel_traits<bits32>::max_value()) return channel_traits<bits32f>::max_value();
308  return float(x) / float(channel_traits<bits32>::max_value());
309  }
310 };
312 template <> struct channel_converter_unsigned<bits32f,bits32> {
313  typedef bits32f argument_type;
314  typedef bits32 result_type;
315  bits32 operator()(bits32f x) const {
316  // 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
318  return bits32(x * channel_traits<bits32>::max_value() + 0.5f);
319  }
320 };
321 
323 
324 namespace detail {
325 // Converting from signed to unsigned integral channel.
326 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
327 template <typename ChannelValue> // Model ChannelValueConcept
328 struct channel_convert_to_unsigned : public detail::identity<ChannelValue> {
329  typedef ChannelValue type;
330 };
331 
332 template <> struct channel_convert_to_unsigned<bits8s> {
333  typedef bits8s argument_type;
334  typedef bits8 result_type;
335  typedef bits8 type;
336  type operator()(bits8s val) const {
337  return static_cast<bits8>(static_cast<bits32>(val) + 128u);
338  }
339 };
340 
341 template <> struct channel_convert_to_unsigned<bits16s> {
342  typedef bits16s argument_type;
343  typedef bits16 result_type;
344  typedef bits16 type;
345  type operator()(bits16s val) const {
346  return static_cast<bits16>(static_cast<bits32>(val) + 32768u);
347  }
348 };
349 
350 template <> struct channel_convert_to_unsigned<bits32s> {
351  typedef bits32s argument_type;
352  typedef bits32 result_type;
353  typedef bits32 type;
354  type operator()(bits32s val) const {
355  return static_cast<bits32>(val)+(1u<<31);
356  }
357 };
358 
359 
360 // Converting from unsigned to signed integral channel
361 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
362 template <typename ChannelValue> // Model ChannelValueConcept
363 struct channel_convert_from_unsigned : public detail::identity<ChannelValue> {
364  typedef ChannelValue type;
365 };
366 
367 template <> struct channel_convert_from_unsigned<bits8s> {
368  typedef bits8 argument_type;
369  typedef bits8s result_type;
370  typedef bits8s type;
371  type operator()(bits8 val) const {
372  return static_cast<bits8s>(static_cast<bits32s>(val) - 128);
373  }
374 };
375 
376 template <> struct channel_convert_from_unsigned<bits16s> {
377  typedef bits16 argument_type;
378  typedef bits16s result_type;
379  typedef bits16s type;
380  type operator()(bits16 val) const {
381  return static_cast<bits16s>(static_cast<bits32s>(val) - 32768);
382  }
383 };
384 
385 template <> struct channel_convert_from_unsigned<bits32s> {
386  typedef bits32 argument_type;
387  typedef bits32s result_type;
388  typedef bits32s type;
389  type operator()(bits32 val) const {
390  return static_cast<bits32s>(val - (1u<<31));
391  }
392 };
393 
394 } // namespace detail
395 
398 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
400  typedef SrcChannelV argument_type;
401  typedef DstChannelV result_type;
402  DstChannelV operator()(const SrcChannelV& src) const {
403  typedef detail::channel_convert_to_unsigned<SrcChannelV> to_unsigned;
404  typedef detail::channel_convert_from_unsigned<DstChannelV> from_unsigned;
405  typedef channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type> converter_unsigned;
406  return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
407  }
408 };
409 
412 template <typename DstChannel, typename SrcChannel> // Model ChannelConcept (could be channel references)
413 inline typename channel_traits<DstChannel>::value_type channel_convert(const SrcChannel& src) {
415  typename channel_traits<DstChannel>::value_type>()(src);
416 }
417 
423  template <typename Ch1, typename Ch2>
424  void operator()(const Ch1& src, Ch2& dst) const {
425  dst=channel_convert<Ch2>(src);
426  }
427 };
428 
429 namespace detail {
430  // fast integer division by 255
431  inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; }
432 
433  // fast integer divison by 32768
434  inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; }
435 }
436 
450 
453 template <typename ChannelValue>
455  typedef ChannelValue first_argument_type;
456  typedef ChannelValue second_argument_type;
457  typedef ChannelValue result_type;
458  ChannelValue operator()(ChannelValue a, ChannelValue b) const {
459  return ChannelValue(static_cast<typename base_channel_type<ChannelValue>::type>(a / double(channel_traits<ChannelValue>::max_value()) * b));
460  }
461 };
462 
464 template<> struct channel_multiplier_unsigned<bits8> {
465  typedef bits8 first_argument_type;
466  typedef bits8 second_argument_type;
467  typedef bits8 result_type;
468  bits8 operator()(bits8 a, bits8 b) const { return bits8(detail::div255(uint32_t(a) * uint32_t(b))); }
469 };
470 
472 template<> struct channel_multiplier_unsigned<bits16> {
473  typedef bits16 first_argument_type;
474  typedef bits16 second_argument_type;
475  typedef bits16 result_type;
476  bits16 operator()(bits16 a, bits16 b) const { return bits16((uint32_t(a) * uint32_t(b))/65535); }
477 };
478 
483  typedef bits32f result_type;
484  bits32f operator()(bits32f a, bits32f b) const { return a*b; }
485 };
486 
488 template <typename ChannelValue>
490  typedef ChannelValue first_argument_type;
491  typedef ChannelValue second_argument_type;
492  typedef ChannelValue result_type;
493  ChannelValue operator()(ChannelValue a, ChannelValue b) const {
494  typedef detail::channel_convert_to_unsigned<ChannelValue> to_unsigned;
495  typedef detail::channel_convert_from_unsigned<ChannelValue> from_unsigned;
497  return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
498  }
499 };
500 
502 template <typename Channel> // Models ChannelConcept (could be a channel reference)
503 inline typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b) {
505 }
507 
522 template <typename Channel> // Models ChannelConcept (could be a channel reference)
527 }
528 
529 //#ifdef _MSC_VER
530 //#pragma warning(pop)
531 //#endif
532 
533 } } // namespace boost::gil
534 
535 #endif
channel_traits< Channel >::value_type channel_invert(Channel x)
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:525
A channel adaptor that modifies the range of the source channel. Models: ChannelValueConcept.
Definition: channel.hpp:155
channel_traits< DstChannel >::value_type channel_convert(const SrcChannel &src)
Converting from one channel type to another.
Definition: channel_algorithm.hpp:413
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:503
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:422
A function object to multiply two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:489
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:454
Traits for channels. Contains the following members:
Definition: channel.hpp:113
GIL configuration file.
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:46
A unary function object converting between channel types.
Definition: channel_algorithm.hpp:399