12 #ifndef GIL_CHANNEL_ALGORITHM_HPP
13 #define GIL_CHANNEL_ALGORITHM_HPP
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>
37 namespace boost {
namespace gil {
48 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcIsGreater>
struct channel_converter_unsigned_integral;
49 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcLessThanDst,
bool SrcDivisible>
struct channel_converter_unsigned_integral_impl;
50 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcLessThanDst,
bool CannotFitInInteger>
struct channel_converter_unsigned_integral_nondivisible;
57 template <
typename Un
signedIntegralChannel>
58 struct unsigned_integral_max_value :
public mpl::integral_c<UnsignedIntegralChannel,integer_traits< UnsignedIntegralChannel>::const_max> {};
61 struct unsigned_integral_max_value<uint8_t> :
public mpl::integral_c<uint32_t,0xFF> {};
63 struct unsigned_integral_max_value<uint16_t> :
public mpl::integral_c<uint32_t,0xFFFF> {};
65 struct unsigned_integral_max_value<uint32_t> :
public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
69 struct unsigned_integral_max_value<packed_channel_value<K> >
70 :
public mpl::integral_c<typename packed_channel_value<K>::integer_t, (uint64_t(1)<<K)-1> {};
78 template <typename UnsignedIntegralChannel>
79 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
82 struct unsigned_integral_num_bits<packed_channel_value<K> >
83 : public mpl::int_<K> {};
124 template <typename SrcChannelV, typename DstChannelV>
125 struct channel_converter_unsigned
126 : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
130 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
140 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
141 struct channel_converter_unsigned_impl {
142 typedef SrcChannelV argument_type;
143 typedef DstChannelV result_type;
144 DstChannelV operator()(SrcChannelV src) const {
145 return DstChannelV(channel_traits<DstChannelV>::min_value() +
146 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
149 template <typename C>
150 static double channel_range() {
151 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
156 template <typename SrcChannelV, typename DstChannelV>
157 struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true>
158 : public channel_converter_unsigned_integral<SrcChannelV,DstChannelV,
159 mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {};
166 template <typename SrcChannelV, typename DstChannelV>
167 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
168 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
169 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
171 template <typename SrcChannelV, typename DstChannelV>
172 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
173 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
174 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
184 template <typename SrcChannelV, typename DstChannelV>
185 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
186 DstChannelV operator()(SrcChannelV src) const {
187 typedef typename unsigned_integral_max_value<DstChannelV>::value_type integer_t;
188 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
189 return DstChannelV(src * mul);
196 template <typename SrcChannelV, typename DstChannelV>
197 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
198 DstChannelV operator()(SrcChannelV src) const {
199 typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t;
200 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
201 static const integer_t div2 = div/2;
202 return DstChannelV((src + div2) / div);
207 template <typename DstChannelV>
208 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
209 DstChannelV operator()(uintmax_t src) const {
210 static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
211 static const uintmax_t div2 = div/2;
212 if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
213 return unsigned_integral_max_value<DstChannelV>::value;
214 return DstChannelV((src + div2) / div);
221 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
222 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false>
223 : public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,
225 mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
226 unsigned_integral_num_bits<uintmax_t>
234 template <typename SrcChannelV, typename DstChannelV>
235 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
236 DstChannelV operator()(SrcChannelV src) const {
237 typedef typename base_channel_type<DstChannelV>::type dest_t;
238 return DstChannelV(static_cast<dest_t>( src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
246 template <typename SrcChannelV, typename DstChannelV>
247 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> {
248 DstChannelV operator()(SrcChannelV src) const {
249 static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value);
250 return DstChannelV(src * mul);
257 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
258 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
259 DstChannelV operator()(SrcChannelV src) const {
261 typedef typename detail::unsigned_integral_max_value< SrcChannelV >::value_type src_integer_t;
262 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
264 static const double div = unsigned_integral_max_value<SrcChannelV>::value
265 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
267 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
269 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
279 template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstChannelV> {
280 typedef float32_t argument_type;
281 typedef DstChannelV result_type;
282 DstChannelV operator()(float32_t x) const
284 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
285 return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
289 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,float32_t> {
290 typedef float32_t argument_type;
291 typedef SrcChannelV result_type;
292 float32_t operator()(SrcChannelV x) const { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
295 template <> struct channel_converter_unsigned<float32_t,float32_t> {
296 typedef float32_t argument_type;
297 typedef float32_t result_type;
298 float32_t operator()(float32_t x) const { return x; }
303 template <> struct channel_converter_unsigned<uint32_t,float32_t> {
304 typedef uint32_t argument_type;
305 typedef float32_t result_type;
306 float32_t operator()(uint32_t x) const {
308 if (x>=channel_traits<uint32_t>::max_value()) return
channel_traits<float32_t>::max_value();
309 return float(x) / float(channel_traits<uint32_t>::max_value());
313 template <> struct channel_converter_unsigned<float32_t,uint32_t> {
315 typedef uint32_t result_type;
322 auto const result = x *
static_cast<float32_t::base_channel_t
>(max_value) + 0.5f;
323 return static_cast<uint32_t
>(result);
332 template <
typename ChannelValue>
333 struct channel_convert_to_unsigned :
public detail::identity<ChannelValue> {
334 typedef ChannelValue type;
337 template <>
struct channel_convert_to_unsigned<int8_t> {
338 typedef int8_t argument_type;
339 typedef uint8_t result_type;
340 typedef uint8_t type;
341 type operator()(int8_t val)
const {
342 return static_cast<uint8_t
>(
static_cast<uint32_t
>(val) + 128u);
346 template <>
struct channel_convert_to_unsigned<int16_t> {
347 typedef int16_t argument_type;
348 typedef uint16_t result_type;
349 typedef uint16_t type;
350 type operator()(int16_t val)
const {
351 return static_cast<uint16_t
>(
static_cast<uint32_t
>(val) + 32768u);
355 template <>
struct channel_convert_to_unsigned<int32_t> {
356 typedef int32_t argument_type;
357 typedef uint32_t result_type;
358 typedef uint32_t type;
359 type operator()(int32_t val)
const {
360 return static_cast<uint32_t
>(val)+(1u<<31);
367 template <
typename ChannelValue>
368 struct channel_convert_from_unsigned :
public detail::identity<ChannelValue> {
369 typedef ChannelValue type;
372 template <>
struct channel_convert_from_unsigned<int8_t> {
373 typedef uint8_t argument_type;
374 typedef int8_t result_type;
376 type operator()(uint8_t val)
const {
377 return static_cast<int8_t
>(
static_cast<int32_t
>(val) - 128);
381 template <>
struct channel_convert_from_unsigned<int16_t> {
382 typedef uint16_t argument_type;
383 typedef int16_t result_type;
384 typedef int16_t type;
385 type operator()(uint16_t val)
const {
386 return static_cast<int16_t
>(
static_cast<int32_t
>(val) - 32768);
390 template <>
struct channel_convert_from_unsigned<int32_t> {
391 typedef uint32_t argument_type;
392 typedef int32_t result_type;
393 typedef int32_t type;
394 type operator()(uint32_t val)
const {
395 return static_cast<int32_t
>(val - (1u<<31));
403 template <
typename SrcChannelV,
typename DstChannelV>
405 typedef SrcChannelV argument_type;
406 typedef DstChannelV result_type;
407 DstChannelV operator()(
const SrcChannelV& src)
const {
408 typedef detail::channel_convert_to_unsigned<SrcChannelV> to_unsigned;
409 typedef detail::channel_convert_from_unsigned<DstChannelV> from_unsigned;
410 typedef channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type> converter_unsigned;
411 return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
417 template <
typename DstChannel,
typename SrcChannel>
428 template <
typename Ch1,
typename Ch2>
429 void operator()(
const Ch1& src, Ch2& dst)
const {
430 dst=channel_convert<Ch2>(src);
436 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128;
return (tmp + (tmp>>8))>>8; }
439 inline uint32_t div32768(uint32_t in) {
return (in+16384)>>15; }
458 template <
typename ChannelValue>
460 typedef ChannelValue first_argument_type;
461 typedef ChannelValue second_argument_type;
462 typedef ChannelValue result_type;
463 ChannelValue operator()(ChannelValue a, ChannelValue b)
const {
470 typedef uint8_t first_argument_type;
471 typedef uint8_t second_argument_type;
472 typedef uint8_t result_type;
473 uint8_t operator()(uint8_t a, uint8_t b)
const {
return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
478 typedef uint16_t first_argument_type;
479 typedef uint16_t second_argument_type;
480 typedef uint16_t result_type;
481 uint16_t operator()(uint16_t a, uint16_t b)
const {
return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
493 template <
typename ChannelValue>
495 typedef ChannelValue first_argument_type;
496 typedef ChannelValue second_argument_type;
497 typedef ChannelValue result_type;
498 ChannelValue operator()(ChannelValue a, ChannelValue b)
const {
499 typedef detail::channel_convert_to_unsigned<ChannelValue> to_unsigned;
500 typedef detail::channel_convert_from_unsigned<ChannelValue> from_unsigned;
502 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
507 template <
typename Channel>
527 template <
typename Channel>
channel_traits< Channel >::value_type channel_invert(Channel x)
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:530
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:418
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:508
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:427
A function object to multiply two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:494
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:459
Traits for channels. Contains the following members:
Definition: channel.hpp:114
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:47
A unary function object converting between channel types.
Definition: channel_algorithm.hpp:404