8 #ifndef BOOST_GIL_GIL_CHANNEL_ALGORITHM_HPP 9 #define BOOST_GIL_GIL_CHANNEL_ALGORITHM_HPP 11 #include <boost/gil/channel.hpp> 12 #include <boost/gil/promote_integral.hpp> 13 #include <boost/gil/typedefs.hpp> 15 #include <boost/mpl/less.hpp> 16 #include <boost/mpl/integral_c.hpp> 17 #include <boost/mpl/greater.hpp> 18 #include <boost/type_traits.hpp> 22 namespace boost {
namespace gil {
28 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcIsGreater>
struct channel_converter_unsigned_integral;
29 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcLessThanDst,
bool SrcDivisible>
struct channel_converter_unsigned_integral_impl;
30 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcLessThanDst,
bool CannotFitInInteger>
struct channel_converter_unsigned_integral_nondivisible;
37 template <
typename Un
signedIntegralChannel>
38 struct unsigned_integral_max_value :
public mpl::integral_c<UnsignedIntegralChannel,std::numeric_limits<UnsignedIntegralChannel>::max()> {};
41 struct unsigned_integral_max_value<uint8_t> :
public mpl::integral_c<uint32_t,0xFF> {};
43 struct unsigned_integral_max_value<uint16_t> :
public mpl::integral_c<uint32_t,0xFFFF> {};
45 struct unsigned_integral_max_value<uint32_t> :
public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
49 struct unsigned_integral_max_value<packed_channel_value<K> >
50 :
public mpl::integral_c<typename packed_channel_value<K>::integer_t, (uint64_t(1)<<K)-1> {};
58 template <typename UnsignedIntegralChannel>
59 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
62 struct unsigned_integral_num_bits<packed_channel_value<K> >
63 : public mpl::int_<K> {};
103 template <typename SrcChannelV, typename DstChannelV>
104 struct channel_converter_unsigned
105 : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
109 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
119 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
120 struct channel_converter_unsigned_impl {
121 using argument_type = SrcChannelV;
122 using result_type = DstChannelV;
123 DstChannelV operator()(SrcChannelV src) const {
124 return DstChannelV(channel_traits<DstChannelV>::min_value() +
125 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
128 template <typename C>
129 static double channel_range() {
130 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
135 template <typename SrcChannelV, typename DstChannelV>
136 struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true>
137 : public channel_converter_unsigned_integral<SrcChannelV,DstChannelV,
138 mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {};
145 template <typename SrcChannelV, typename DstChannelV>
146 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
147 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
148 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
150 template <typename SrcChannelV, typename DstChannelV>
151 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
152 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
153 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
163 template <typename SrcChannelV, typename DstChannelV>
164 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
165 DstChannelV operator()(SrcChannelV src) const {
166 using integer_t = typename unsigned_integral_max_value<DstChannelV>::value_type;
167 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
168 return DstChannelV(src * mul);
175 template <typename SrcChannelV, typename DstChannelV>
176 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
177 DstChannelV operator()(SrcChannelV src) const {
178 using integer_t = typename unsigned_integral_max_value<SrcChannelV>::value_type;
179 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
180 static const integer_t div2 = div/2;
181 return DstChannelV((src + div2) / div);
186 template <typename DstChannelV>
187 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
188 DstChannelV operator()(uintmax_t src) const {
189 static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
190 static const uintmax_t div2 = div/2;
191 if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
192 return unsigned_integral_max_value<DstChannelV>::value;
193 return DstChannelV((src + div2) / div);
200 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
201 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false>
202 : public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,
204 mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
205 unsigned_integral_num_bits<uintmax_t>
213 template <typename SrcChannelV, typename DstChannelV>
214 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
215 DstChannelV operator()(SrcChannelV src) const {
216 using dest_t = typename base_channel_type<DstChannelV>::type;
217 return DstChannelV(static_cast<dest_t>( src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
225 template <typename SrcChannelV, typename DstChannelV>
226 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> {
227 DstChannelV operator()(SrcChannelV src) const {
228 static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value);
229 return DstChannelV(src * mul);
236 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
237 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
238 DstChannelV operator()(SrcChannelV src) const {
240 using src_integer_t = typename detail::unsigned_integral_max_value<SrcChannelV>::value_type;
241 using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
243 static const double div = unsigned_integral_max_value<SrcChannelV>::value
244 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
246 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
248 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
258 template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstChannelV> {
259 using argument_type = float32_t;
260 using result_type = DstChannelV;
261 DstChannelV operator()(float32_t x) const
263 using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
264 return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
268 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,float32_t> {
269 using argument_type = float32_t;
270 using result_type = SrcChannelV;
271 float32_t operator()(SrcChannelV x) const { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
274 template <> struct channel_converter_unsigned<float32_t,float32_t> {
275 using argument_type = float32_t;
276 using result_type = float32_t;
277 float32_t operator()(float32_t x) const { return x; }
282 template <> struct channel_converter_unsigned<uint32_t,float32_t> {
283 using argument_type = uint32_t;
284 using result_type = float32_t;
285 float32_t operator()(uint32_t x) const {
287 if (x>=channel_traits<uint32_t>::max_value()) return channel_traits<float32_t>::max_value();
288 return float(x) / float(channel_traits<uint32_t>::max_value());
292 template <> struct channel_converter_unsigned<float32_t,uint32_t> {
294 using result_type = uint32_t;
297 if (x>=channel_traits<float32_t>::max_value())
298 return channel_traits<uint32_t>::max_value();
300 auto const max_value = channel_traits<uint32_t>::max_value();
301 auto const result = x *
static_cast<float32_t::base_channel_t
>(max_value) + 0.5f;
302 return static_cast<uint32_t
>(result);
311 template <
typename ChannelValue>
312 struct channel_convert_to_unsigned :
public detail::identity<ChannelValue> {
313 using type = ChannelValue;
316 template <>
struct channel_convert_to_unsigned<int8_t> {
317 using argument_type = int8_t;
318 using result_type = uint8_t;
319 using type = uint8_t;
320 type operator()(int8_t val)
const {
321 return static_cast<uint8_t
>(
static_cast<uint32_t
>(val) + 128u);
325 template <>
struct channel_convert_to_unsigned<int16_t> {
326 using argument_type = int16_t;
327 using result_type = uint16_t;
328 using type = uint16_t;
329 type operator()(int16_t val)
const {
330 return static_cast<uint16_t
>(
static_cast<uint32_t
>(val) + 32768u);
334 template <>
struct channel_convert_to_unsigned<int32_t> {
335 using argument_type = int32_t;
336 using result_type = uint32_t;
337 using type = uint32_t;
338 type operator()(int32_t val)
const {
339 return static_cast<uint32_t
>(val)+(1u<<31);
346 template <
typename ChannelValue>
347 struct channel_convert_from_unsigned :
public detail::identity<ChannelValue> {
348 using type = ChannelValue;
351 template <>
struct channel_convert_from_unsigned<int8_t> {
352 using argument_type = uint8_t;
353 using result_type = int8_t;
355 type operator()(uint8_t val)
const {
356 return static_cast<int8_t
>(
static_cast<int32_t
>(val) - 128);
360 template <>
struct channel_convert_from_unsigned<int16_t> {
361 using argument_type = uint16_t;
362 using result_type = int16_t;
363 using type = int16_t;
364 type operator()(uint16_t val)
const {
365 return static_cast<int16_t
>(
static_cast<int32_t
>(val) - 32768);
369 template <>
struct channel_convert_from_unsigned<int32_t> {
370 using argument_type = uint32_t;
371 using result_type = int32_t;
372 using type = int32_t;
373 type operator()(uint32_t val)
const {
374 return static_cast<int32_t
>(val - (1u<<31));
382 template <
typename SrcChannelV,
typename DstChannelV>
384 using argument_type = SrcChannelV;
385 using result_type = DstChannelV;
386 DstChannelV operator()(
const SrcChannelV& src)
const {
387 using to_unsigned = detail::channel_convert_to_unsigned<SrcChannelV>;
388 using from_unsigned = detail::channel_convert_from_unsigned<DstChannelV>;
389 using converter_unsigned = channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type>;
390 return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
396 template <
typename DstChannel,
typename SrcChannel>
397 inline typename channel_traits<DstChannel>::value_type
channel_convert(
const SrcChannel& src) {
399 typename channel_traits<DstChannel>::value_type>()(src);
407 template <
typename Ch1,
typename Ch2>
408 void operator()(
const Ch1& src, Ch2& dst)
const {
409 dst=channel_convert<Ch2>(src);
415 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128;
return (tmp + (tmp>>8))>>8; }
418 inline uint32_t div32768(uint32_t in) {
return (in+16384)>>15; }
435 template <
typename ChannelValue>
437 using first_argument_type = ChannelValue;
438 using second_argument_type = ChannelValue;
439 using result_type = ChannelValue;
440 ChannelValue operator()(ChannelValue a, ChannelValue b)
const {
441 return ChannelValue(
static_cast<typename base_channel_type<ChannelValue>::type
>(a /
double(channel_traits<ChannelValue>::max_value()) * b));
447 using first_argument_type = uint8_t;
448 using second_argument_type = uint8_t;
449 using result_type = uint8_t;
450 uint8_t operator()(uint8_t a, uint8_t b)
const {
return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
455 using first_argument_type = uint16_t;
456 using second_argument_type = uint16_t;
457 using result_type = uint16_t;
458 uint16_t operator()(uint16_t a, uint16_t b)
const {
return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
470 template <
typename ChannelValue>
472 using first_argument_type = ChannelValue;
473 using second_argument_type = ChannelValue;
474 using result_type = ChannelValue;
475 ChannelValue operator()(ChannelValue a, ChannelValue b)
const {
476 using to_unsigned = detail::channel_convert_to_unsigned<ChannelValue>;
477 using from_unsigned = detail::channel_convert_from_unsigned<ChannelValue>;
479 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
484 template <
typename Channel>
485 inline typename channel_traits<Channel>::value_type
channel_multiply(Channel a, Channel b) {
504 template <
typename Channel>
507 using base_t =
typename base_channel_type<Channel>::type;
508 using promoted_t =
typename promote_integral<base_t>::type;
509 promoted_t
const promoted_x = x;
510 promoted_t
const promoted_max = channel_traits<Channel>::max_value();
511 promoted_t
const promoted_min = channel_traits<Channel>::min_value();
512 promoted_t
const promoted_inverted_x = promoted_max - promoted_x + promoted_min;
513 auto const inverted_x =
static_cast<base_t
>(promoted_inverted_x);
channel_traits< Channel >::value_type channel_invert(Channel x)
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:505
Definition: algorithm.hpp:30
scoped_channel_value< float, float_point_zero< float >, float_point_one< float > > float32_t
32-bit floating point channel type with range [0.0f ... 1.0f]. Models ChannelValueConcept ...
Definition: typedefs.hpp:124
channel_traits< DstChannel >::value_type channel_convert(const SrcChannel &src)
Converting from one channel type to another.
Definition: channel_algorithm.hpp:397
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:485
identity taken from SGI STL.
Definition: utilities.hpp:193
Same as channel_converter, except it takes the destination channel by reference, which allows us to m...
Definition: channel_algorithm.hpp:406
A function object to multiply two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:471
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:436
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:27
A unary function object converting between channel types.
Definition: channel_algorithm.hpp:383