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>
36 namespace boost {
namespace gil {
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;
56 template <
typename Un
signedIntegralChannel>
57 struct unsigned_integral_max_value :
public mpl::integral_c<UnsignedIntegralChannel,integer_traits< UnsignedIntegralChannel>::const_max> {};
60 struct unsigned_integral_max_value<uint8_t> :
public mpl::integral_c<uint32_t,0xFF> {};
62 struct unsigned_integral_max_value<uint16_t> :
public mpl::integral_c<uint32_t,0xFFFF> {};
64 struct unsigned_integral_max_value<uint32_t> :
public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
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> {};
77 template <typename UnsignedIntegralChannel>
78 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
81 struct unsigned_integral_num_bits<packed_channel_value<K> >
82 : public mpl::int_<K> {};
123 template <typename SrcChannelV, typename DstChannelV>
124 struct channel_converter_unsigned
125 : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
129 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
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>());
148 template <typename C>
149 static double channel_range() {
150 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
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 > {};
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) > {};
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) > {};
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);
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);
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);
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,
224 mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
225 unsigned_integral_num_bits<uintmax_t>
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);
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);
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 {
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;
263 static const double div = unsigned_integral_max_value<SrcChannelV>::value
264 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
266 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
268 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
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
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 ));
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())); }
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; }
302 template <> struct channel_converter_unsigned<bits32,bits32f> {
303 typedef bits32 argument_type;
304 typedef bits32f result_type;
305 bits32f operator()(bits32 x) const {
307 if (x>=channel_traits<bits32>::max_value()) return
channel_traits<bits32f>::max_value();
308 return float(x) / float(channel_traits<bits32>::max_value());
312 template <> struct channel_converter_unsigned<bits32f,bits32> {
314 typedef bits32 result_type;
315 bits32 operator()(
bits32f x)
const {
327 template <
typename ChannelValue>
328 struct channel_convert_to_unsigned :
public detail::identity<ChannelValue> {
329 typedef ChannelValue type;
332 template <>
struct channel_convert_to_unsigned<bits8s> {
333 typedef bits8s argument_type;
334 typedef bits8 result_type;
336 type operator()(bits8s val)
const {
337 return static_cast<bits8
>(
static_cast<bits32
>(val) + 128u);
341 template <>
struct channel_convert_to_unsigned<bits16s> {
342 typedef bits16s argument_type;
343 typedef bits16 result_type;
345 type operator()(bits16s val)
const {
346 return static_cast<bits16
>(
static_cast<bits32
>(val) + 32768u);
350 template <>
struct channel_convert_to_unsigned<bits32s> {
351 typedef bits32s argument_type;
352 typedef bits32 result_type;
354 type operator()(bits32s val)
const {
355 return static_cast<bits32
>(val)+(1u<<31);
362 template <
typename ChannelValue>
363 struct channel_convert_from_unsigned :
public detail::identity<ChannelValue> {
364 typedef ChannelValue type;
367 template <>
struct channel_convert_from_unsigned<bits8s> {
368 typedef bits8 argument_type;
369 typedef bits8s result_type;
371 type operator()(bits8 val)
const {
372 return static_cast<bits8s
>(
static_cast<bits32s
>(val) - 128);
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);
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));
398 template <
typename SrcChannelV,
typename DstChannelV>
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)));
412 template <
typename DstChannel,
typename SrcChannel>
423 template <
typename Ch1,
typename Ch2>
424 void operator()(
const Ch1& src, Ch2& dst)
const {
425 dst=channel_convert<Ch2>(src);
431 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128;
return (tmp + (tmp>>8))>>8; }
434 inline uint32_t div32768(uint32_t in) {
return (in+16384)>>15; }
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 {
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))); }
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); }
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)));
502 template <
typename Channel>
522 template <
typename Channel>
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_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
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