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>
14 #include <boost/gil/detail/is_channel_integral.hpp>
15 #include <boost/gil/detail/mp11.hpp>
18 #include <type_traits>
20 namespace boost {
namespace gil {
25 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcIsIntegral,
bool DstIsIntegral>
26 struct channel_converter_unsigned_impl;
28 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcIsGreater>
29 struct channel_converter_unsigned_integral;
31 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcLessThanDst,
bool SrcDivisible>
32 struct channel_converter_unsigned_integral_impl;
34 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcLessThanDst,
bool CannotFitInInteger>
35 struct channel_converter_unsigned_integral_nondivisible;
42 template <
typename Un
signedIntegralChannel>
43 struct unsigned_integral_max_value
44 : std::integral_constant
46 UnsignedIntegralChannel,
47 (std::numeric_limits<UnsignedIntegralChannel>::max)()
52 struct unsigned_integral_max_value<uint8_t>
53 : std::integral_constant<uint32_t, 0xFF>
57 struct unsigned_integral_max_value<uint16_t>
58 : std::integral_constant<uint32_t, 0xFFFF>
62 struct unsigned_integral_max_value<uint32_t>
63 : std::integral_constant<uintmax_t, 0xFFFFFFFF>
67 struct unsigned_integral_max_value<packed_channel_value<K>>
68 : std::integral_constant
70 typename packed_channel_value<K>::integer_t,
80 template <typename UnsignedIntegralChannel>
81 struct unsigned_integral_num_bits
82 : std::integral_constant<int, static_cast<int>(sizeof(UnsignedIntegralChannel) * 8)>
86 struct unsigned_integral_num_bits<packed_channel_value<K>>
87 : std::integral_constant<int, K>
126 template <typename SrcChannelV, typename DstChannelV>
127 struct channel_converter_unsigned
128 : detail::channel_converter_unsigned_impl
132 detail::is_channel_integral<SrcChannelV>::value,
133 detail::is_channel_integral<DstChannelV>::value
138 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
147 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
148 struct channel_converter_unsigned_impl {
149 using argument_type = SrcChannelV;
150 using result_type = DstChannelV;
151 auto operator()(SrcChannelV src) const -> DstChannelV
153 return DstChannelV(channel_traits<DstChannelV>::min_value() +
154 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
158 template <typename C>
159 static auto channel_range() -> double
161 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
166 template <
typename SrcChannelV,
typename DstChannelV>
167 struct channel_converter_unsigned_impl<SrcChannelV, DstChannelV, true, true>
168 : channel_converter_unsigned_integral
174 unsigned_integral_max_value<SrcChannelV>,
175 unsigned_integral_max_value<DstChannelV>
184 template <
typename SrcChannelV,
typename DstChannelV>
185 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
186 :
public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
187 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
189 template <
typename SrcChannelV,
typename DstChannelV>
190 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
191 :
public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
192 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
202 template <
typename SrcChannelV,
typename DstChannelV>
203 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
204 auto operator()(SrcChannelV src)
const -> DstChannelV
206 using integer_t =
typename unsigned_integral_max_value<DstChannelV>::value_type;
207 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
208 return DstChannelV(src * mul);
215 template <
typename SrcChannelV,
typename DstChannelV>
216 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
217 auto operator()(SrcChannelV src)
const -> DstChannelV
219 using integer_t =
typename unsigned_integral_max_value<SrcChannelV>::value_type;
220 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
221 static const integer_t div2 = div/2;
222 return DstChannelV((src + div2) / div);
227 template <
typename DstChannelV>
228 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
229 auto operator()(uintmax_t src)
const -> DstChannelV
231 static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
232 static const uintmax_t div2 = div/2;
233 if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
234 return unsigned_integral_max_value<DstChannelV>::value;
235 return DstChannelV((src + div2) / div);
242 template <
typename SrcChannelV,
typename DstChannelV,
bool SrcLessThanDst>
243 struct channel_converter_unsigned_integral_impl<SrcChannelV, DstChannelV, SrcLessThanDst, false>
244 : channel_converter_unsigned_integral_nondivisible
251 unsigned_integral_num_bits<uintmax_t>,
254 unsigned_integral_num_bits<SrcChannelV>,
255 unsigned_integral_num_bits<DstChannelV>
265 template <
typename SrcChannelV,
typename DstChannelV>
266 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, false>
268 auto operator()(SrcChannelV src)
const -> DstChannelV
270 using dest_t =
typename base_channel_type<DstChannelV>::type;
272 static_cast<dest_t
>(src * unsigned_integral_max_value<DstChannelV>::value)
273 / unsigned_integral_max_value<SrcChannelV>::value);
281 template <
typename SrcChannelV,
typename DstChannelV>
282 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, true>
284 auto operator()(SrcChannelV src)
const -> DstChannelV
286 static const double mul
287 = unsigned_integral_max_value<DstChannelV>::value
288 / double(unsigned_integral_max_value<SrcChannelV>::value);
289 return DstChannelV(src * mul);
296 template <
typename SrcChannelV,
typename DstChannelV,
bool CannotFit>
297 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit>
299 auto operator()(SrcChannelV src)
const -> DstChannelV
301 using src_integer_t =
typename detail::unsigned_integral_max_value<SrcChannelV>::value_type;
302 using dst_integer_t =
typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
304 static const double div = unsigned_integral_max_value<SrcChannelV>::value
305 /
static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
307 static const src_integer_t div2 =
static_cast< src_integer_t
>( div / 2.0 );
309 return DstChannelV(
static_cast< dst_integer_t
>((
static_cast< double >( src + div2 ) / div )));
319 template <
typename DstChannelV>
struct channel_converter_unsigned<
float32_t,DstChannelV> {
321 using result_type = DstChannelV;
322 auto operator()(
float32_t x)
const -> DstChannelV
324 using dst_integer_t =
typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
325 return DstChannelV(
static_cast< dst_integer_t
>(x*channel_traits<DstChannelV>::max_value()+0.5f ));
329 template <
typename SrcChannelV>
struct channel_converter_unsigned<SrcChannelV,
float32_t> {
331 using result_type = SrcChannelV;
332 auto operator()(SrcChannelV x)
const ->
float32_t {
return float32_t(x/
float(channel_traits<SrcChannelV>::max_value())); }
343 template <>
struct channel_converter_unsigned<uint32_t,
float32_t> {
344 using argument_type = uint32_t;
346 auto operator()(uint32_t x)
const ->
float32_t
349 if (x>=channel_traits<uint32_t>::max_value())
return channel_traits<float32_t>::max_value();
350 return float(x) / float(channel_traits<uint32_t>::max_value());
354 template <>
struct channel_converter_unsigned<
float32_t,uint32_t> {
356 using result_type = uint32_t;
357 auto operator()(
float32_t x)
const -> uint32_t
360 if (x>=channel_traits<float32_t>::max_value())
361 return channel_traits<uint32_t>::max_value();
363 auto const max_value = channel_traits<uint32_t>::max_value();
364 auto const result = x *
static_cast<float32_t::base_channel_t
>(max_value) + 0.5f;
365 return static_cast<uint32_t
>(result);
374 template <
typename ChannelValue>
375 struct channel_convert_to_unsigned :
public detail::identity<ChannelValue> {
376 using type = ChannelValue;
379 template <>
struct channel_convert_to_unsigned<int8_t> {
380 using argument_type = int8_t;
381 using result_type = uint8_t;
382 using type = uint8_t;
383 type operator()(int8_t val)
const {
384 return static_cast<uint8_t
>(
static_cast<uint32_t
>(val) + 128u);
388 template <>
struct channel_convert_to_unsigned<int16_t> {
389 using argument_type = int16_t;
390 using result_type = uint16_t;
391 using type = uint16_t;
392 type operator()(int16_t val)
const {
393 return static_cast<uint16_t
>(
static_cast<uint32_t
>(val) + 32768u);
397 template <>
struct channel_convert_to_unsigned<int32_t> {
398 using argument_type = int32_t;
399 using result_type = uint32_t;
400 using type = uint32_t;
401 type operator()(int32_t val)
const {
402 return static_cast<uint32_t
>(val)+(1u<<31);
409 template <
typename ChannelValue>
410 struct channel_convert_from_unsigned :
public detail::identity<ChannelValue> {
411 using type = ChannelValue;
414 template <>
struct channel_convert_from_unsigned<int8_t> {
415 using argument_type = uint8_t;
416 using result_type = int8_t;
418 type operator()(uint8_t val)
const {
419 return static_cast<int8_t
>(
static_cast<int32_t
>(val) - 128);
423 template <>
struct channel_convert_from_unsigned<int16_t> {
424 using argument_type = uint16_t;
425 using result_type = int16_t;
426 using type = int16_t;
427 type operator()(uint16_t val)
const {
428 return static_cast<int16_t
>(
static_cast<int32_t
>(val) - 32768);
432 template <>
struct channel_convert_from_unsigned<int32_t> {
433 using argument_type = uint32_t;
434 using result_type = int32_t;
435 using type = int32_t;
436 type operator()(uint32_t val)
const {
437 return static_cast<int32_t
>(val - (1u<<31));
445 template <
typename SrcChannelV,
typename DstChannelV>
447 using argument_type = SrcChannelV;
448 using result_type = DstChannelV;
449 auto operator()(SrcChannelV
const& src)
const -> DstChannelV
451 using to_unsigned = detail::channel_convert_to_unsigned<SrcChannelV>;
452 using from_unsigned = detail::channel_convert_from_unsigned<DstChannelV>;
453 using converter_unsigned = channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type>;
454 return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
460 template <
typename DstChannel,
typename SrcChannel>
461 inline auto channel_convert(SrcChannel
const& src) ->
typename channel_traits<DstChannel>::value_type
464 typename channel_traits<DstChannel>::value_type>()(src);
472 template <
typename Ch1,
typename Ch2>
473 void operator()(Ch1
const& src, Ch2& dst)
const
475 dst=channel_convert<Ch2>(src);
482 inline auto div255(uint32_t in) -> uint32_t
484 uint32_t tmp = in + 128;
485 return (tmp + (tmp >> 8)) >> 8;
489 inline auto div32768(uint32_t in) -> uint32_t
491 return (in + 16384) >> 15;
509 template <
typename ChannelValue>
511 using first_argument_type = ChannelValue;
512 using second_argument_type = ChannelValue;
513 using result_type = ChannelValue;
514 auto operator()(ChannelValue a, ChannelValue b)
const -> ChannelValue
516 return ChannelValue(
static_cast<typename base_channel_type<ChannelValue>::type
>(a /
double(channel_traits<ChannelValue>::max_value()) * b));
522 using first_argument_type = uint8_t;
523 using second_argument_type = uint8_t;
524 using result_type = uint8_t;
525 auto operator()(uint8_t a, uint8_t b)
const -> uint8_t {
return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
530 using first_argument_type = uint16_t;
531 using second_argument_type = uint16_t;
532 using result_type = uint16_t;
533 auto operator()(uint16_t a, uint16_t b)
const -> uint16_t {
return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
545 template <
typename ChannelValue>
547 using first_argument_type = ChannelValue;
548 using second_argument_type = ChannelValue;
549 using result_type = ChannelValue;
550 auto operator()(ChannelValue a, ChannelValue b)
const -> ChannelValue
552 using to_unsigned = detail::channel_convert_to_unsigned<ChannelValue>;
553 using from_unsigned = detail::channel_convert_from_unsigned<ChannelValue>;
555 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
560 template <
typename Channel>
561 inline auto channel_multiply(Channel a, Channel b) ->
typename channel_traits<Channel>::value_type
581 template <
typename Channel>
582 inline auto channel_invert(Channel x) ->
typename channel_traits<Channel>::value_type
584 using base_t =
typename base_channel_type<Channel>::type;
585 using promoted_t =
typename promote_integral<base_t>::type;
586 promoted_t
const promoted_x = x;
587 promoted_t
const promoted_max = channel_traits<Channel>::max_value();
588 promoted_t
const promoted_min = channel_traits<Channel>::min_value();
589 promoted_t
const promoted_inverted_x = promoted_max - promoted_x + promoted_min;
590 auto const inverted_x =
static_cast<base_t
>(promoted_inverted_x);
auto channel_convert(SrcChannel const &src) -> typename channel_traits< DstChannel >::value_type
Converting from one channel type to another.
Definition: channel_algorithm.hpp:461
auto channel_invert(Channel x) -> typename channel_traits< Channel >::value_type
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:582
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:153
auto channel_multiply(Channel a, Channel b) -> typename channel_traits< Channel >::value_type
A function multiplying two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:561
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36
A unary function object converting between channel types.
Definition: channel_algorithm.hpp:446
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:510
A function object to multiply two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:546
Same as channel_converter, except it takes the destination channel by reference, which allows us to m...
Definition: channel_algorithm.hpp:471
identity taken from SGI STL.
Definition: utilities.hpp:211