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>
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, 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 DstChannelV operator()(SrcChannelV src) const {
152 return DstChannelV(channel_traits<DstChannelV>::min_value() +
153 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
156 template <typename C>
157 static double channel_range() {
158 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
163 template <typename SrcChannelV, typename DstChannelV>
164 struct channel_converter_unsigned_impl<SrcChannelV, DstChannelV, true, true>
165 : channel_converter_unsigned_integral
171 unsigned_integral_max_value<SrcChannelV>,
172 unsigned_integral_max_value<DstChannelV>
181 template <typename SrcChannelV, typename DstChannelV>
182 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
183 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
184 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
186 template <typename SrcChannelV, typename DstChannelV>
187 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
188 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
189 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
199 template <typename SrcChannelV, typename DstChannelV>
200 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
201 DstChannelV operator()(SrcChannelV src) const {
202 using integer_t = typename unsigned_integral_max_value<DstChannelV>::value_type;
203 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
204 return DstChannelV(src * mul);
211 template <typename SrcChannelV, typename DstChannelV>
212 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
213 DstChannelV operator()(SrcChannelV src) const {
214 using integer_t = typename unsigned_integral_max_value<SrcChannelV>::value_type;
215 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
216 static const integer_t div2 = div/2;
217 return DstChannelV((src + div2) / div);
222 template <typename DstChannelV>
223 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
224 DstChannelV operator()(uintmax_t src) const {
225 static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
226 static const uintmax_t div2 = div/2;
227 if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
228 return unsigned_integral_max_value<DstChannelV>::value;
229 return DstChannelV((src + div2) / div);
236 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
237 struct channel_converter_unsigned_integral_impl<SrcChannelV, DstChannelV, SrcLessThanDst, false>
238 : channel_converter_unsigned_integral_nondivisible
245 unsigned_integral_num_bits<uintmax_t>,
248 unsigned_integral_num_bits<SrcChannelV>,
249 unsigned_integral_num_bits<DstChannelV>
259 template <typename SrcChannelV, typename DstChannelV>
260 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, false>
262 DstChannelV operator()(SrcChannelV src) const
264 using dest_t = typename base_channel_type<DstChannelV>::type;
266 static_cast<dest_t>(src * unsigned_integral_max_value<DstChannelV>::value)
267 / unsigned_integral_max_value<SrcChannelV>::value);
275 template <typename SrcChannelV, typename DstChannelV>
276 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, true>
278 DstChannelV operator()(SrcChannelV src) const
280 static const double mul
281 = unsigned_integral_max_value<DstChannelV>::value
282 / double(unsigned_integral_max_value<SrcChannelV>::value);
283 return DstChannelV(src * mul);
290 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
291 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
292 DstChannelV operator()(SrcChannelV src) const {
294 using src_integer_t = typename detail::unsigned_integral_max_value<SrcChannelV>::value_type;
295 using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
297 static const double div = unsigned_integral_max_value<SrcChannelV>::value
298 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
300 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
302 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
312 template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstChannelV> {
313 using argument_type = float32_t;
314 using result_type = DstChannelV;
315 DstChannelV operator()(float32_t x) const
317 using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
318 return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
322 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,float32_t> {
323 using argument_type = float32_t;
324 using result_type = SrcChannelV;
325 float32_t operator()(SrcChannelV x) const { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
328 template <> struct channel_converter_unsigned<float32_t,float32_t> {
329 using argument_type = float32_t;
330 using result_type = float32_t;
331 float32_t operator()(float32_t x) const { return x; }
336 template <> struct channel_converter_unsigned<uint32_t,float32_t> {
337 using argument_type = uint32_t;
338 using result_type = float32_t;
339 float32_t operator()(uint32_t x) const {
341 if (x>=channel_traits<uint32_t>::max_value()) return channel_traits<float32_t>::max_value();
342 return float(x) / float(channel_traits<uint32_t>::max_value());
346 template <> struct channel_converter_unsigned<float32_t,uint32_t> {
348 using result_type = uint32_t;
351 if (x>=channel_traits<float32_t>::max_value())
352 return channel_traits<uint32_t>::max_value();
354 auto const max_value = channel_traits<uint32_t>::max_value();
355 auto const result = x * static_cast<float32_t::base_channel_t>(max_value) + 0.5f;
356 return static_cast<uint32_t>(result);
365 template <
typename ChannelValue>
366 struct channel_convert_to_unsigned :
public detail::identity<ChannelValue> {
367 using type = ChannelValue;
370 template <>
struct channel_convert_to_unsigned<int8_t> {
371 using argument_type = int8_t;
372 using result_type = uint8_t;
373 using type = uint8_t;
374 type operator()(int8_t val)
const {
375 return static_cast<uint8_t>(static_cast<uint32_t>(val) + 128u);
379 template <>
struct channel_convert_to_unsigned<int16_t> {
380 using argument_type = int16_t;
381 using result_type = uint16_t;
382 using type = uint16_t;
383 type operator()(int16_t val)
const {
384 return static_cast<uint16_t>(static_cast<uint32_t>(val) + 32768u);
388 template <>
struct channel_convert_to_unsigned<int32_t> {
389 using argument_type = int32_t;
390 using result_type = uint32_t;
391 using type = uint32_t;
392 type operator()(int32_t val)
const {
393 return static_cast<uint32_t>(val)+(1u<<31);
400 template <
typename ChannelValue>
401 struct channel_convert_from_unsigned :
public detail::identity<ChannelValue> {
402 using type = ChannelValue;
405 template <>
struct channel_convert_from_unsigned<int8_t> {
406 using argument_type = uint8_t;
407 using result_type = int8_t;
409 type operator()(uint8_t val)
const {
410 return static_cast<int8_t>(static_cast<int32_t>(val) - 128);
414 template <>
struct channel_convert_from_unsigned<int16_t> {
415 using argument_type = uint16_t;
416 using result_type = int16_t;
417 using type = int16_t;
418 type operator()(uint16_t val)
const {
419 return static_cast<int16_t>(static_cast<int32_t>(val) - 32768);
423 template <>
struct channel_convert_from_unsigned<int32_t> {
424 using argument_type = uint32_t;
425 using result_type = int32_t;
426 using type = int32_t;
427 type operator()(uint32_t val)
const {
428 return static_cast<int32_t>(val - (1u<<31));
436 template <
typename SrcChannelV,
typename DstChannelV>
438 using argument_type = SrcChannelV;
439 using result_type = DstChannelV;
440 DstChannelV operator()(
const SrcChannelV& src)
const {
441 using to_unsigned = detail::channel_convert_to_unsigned<SrcChannelV>;
442 using from_unsigned = detail::channel_convert_from_unsigned<DstChannelV>;
443 using converter_unsigned = channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type>;
444 return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
450 template <
typename DstChannel,
typename SrcChannel>
451 inline typename channel_traits<DstChannel>::value_type
channel_convert(
const SrcChannel& src) {
453 typename channel_traits<DstChannel>::value_type>()(src);
461 template <
typename Ch1,
typename Ch2>
462 void operator()(
const Ch1& src, Ch2& dst)
const {
463 dst=channel_convert<Ch2>(src);
469 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128;
return (tmp + (tmp>>8))>>8; }
472 inline uint32_t div32768(uint32_t in) {
return (in+16384)>>15; }
489 template <
typename ChannelValue>
491 using first_argument_type = ChannelValue;
492 using second_argument_type = ChannelValue;
493 using result_type = ChannelValue;
494 ChannelValue operator()(ChannelValue a, ChannelValue b)
const {
495 return ChannelValue(
static_cast<typename base_channel_type<ChannelValue>::type
>(a /
double(channel_traits<ChannelValue>::max_value()) * b));
501 using first_argument_type = uint8_t;
502 using second_argument_type = uint8_t;
503 using result_type = uint8_t;
504 uint8_t operator()(uint8_t a, uint8_t b)
const {
return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
509 using first_argument_type = uint16_t;
510 using second_argument_type = uint16_t;
511 using result_type = uint16_t;
512 uint16_t operator()(uint16_t a, uint16_t b)
const {
return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
524 template <
typename ChannelValue>
526 using first_argument_type = ChannelValue;
527 using second_argument_type = ChannelValue;
528 using result_type = ChannelValue;
529 ChannelValue operator()(ChannelValue a, ChannelValue b)
const {
530 using to_unsigned = detail::channel_convert_to_unsigned<ChannelValue>;
531 using from_unsigned = detail::channel_convert_from_unsigned<ChannelValue>;
533 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
538 template <
typename Channel>
539 inline typename channel_traits<Channel>::value_type
channel_multiply(Channel a, Channel b) {
558 template <
typename Channel>
561 using base_t =
typename base_channel_type<Channel>::type;
562 using promoted_t =
typename promote_integral<base_t>::type;
563 promoted_t
const promoted_x = x;
564 promoted_t
const promoted_max = channel_traits<Channel>::max_value();
565 promoted_t
const promoted_min = channel_traits<Channel>::min_value();
566 promoted_t
const promoted_inverted_x = promoted_max - promoted_x + promoted_min;
567 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:559
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:451
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:539
identity taken from SGI STL.
Definition: utilities.hpp:209
Same as channel_converter, except it takes the destination channel by reference, which allows us to m...
Definition: channel_algorithm.hpp:460
A function object to multiply two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:525
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:490
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:26
A unary function object converting between channel types.
Definition: channel_algorithm.hpp:437