algorithm.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. //
  2. // Copyright 2005-2007 Adobe Systems Incorporated
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. #ifndef BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
  9. #define BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
  10. #include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
  11. #include <boost/gil/metafunctions.hpp>
  12. #include <boost/gil/pixel_iterator.hpp>
  13. #include <boost/assert.hpp>
  14. #include <algorithm>
  15. #include <iterator>
  16. #include <numeric>
  17. namespace boost { namespace gil {
  18. /// \brief Returns the reference proxy associated with a type that has a \p "reference" member type alias.
  19. ///
  20. /// The reference proxy is the reference type, but with stripped-out C++ reference. It models PixelConcept
  21. template <typename T>
  22. struct pixel_proxy : public remove_reference<typename T::reference> {};
  23. /// \brief std::for_each for a pair of iterators
  24. template <typename Iterator1,typename Iterator2,typename BinaryFunction>
  25. BinaryFunction for_each(Iterator1 first1,Iterator1 last1,Iterator2 first2,BinaryFunction f) {
  26. while(first1!=last1)
  27. f(*first1++,*first2++);
  28. return f;
  29. }
  30. template <typename SrcIterator,typename DstIterator>
  31. inline DstIterator assign_pixels(SrcIterator src,SrcIterator src_end,DstIterator dst) {
  32. for_each(src,src_end,dst,pixel_assigns_t<typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
  33. typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type>());
  34. return dst+(src_end-src);
  35. }
  36. namespace detail {
  37. template <std::size_t Size>
  38. struct inner_product_k_t {
  39. template <class _InputIterator1, class _InputIterator2, class _Tp,
  40. class _BinaryOperation1, class _BinaryOperation2>
  41. static _Tp apply(_InputIterator1 __first1,
  42. _InputIterator2 __first2, _Tp __init,
  43. _BinaryOperation1 __binary_op1,
  44. _BinaryOperation2 __binary_op2) {
  45. __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
  46. return inner_product_k_t<Size-1>::template apply(__first1+1,__first2+1,__init,
  47. __binary_op1, __binary_op2);
  48. }
  49. };
  50. template <>
  51. struct inner_product_k_t<0> {
  52. template <class _InputIterator1, class _InputIterator2, class _Tp,
  53. class _BinaryOperation1, class _BinaryOperation2>
  54. static _Tp apply(_InputIterator1 __first1,
  55. _InputIterator2 __first2, _Tp __init,
  56. _BinaryOperation1 __binary_op1,
  57. _BinaryOperation2 __binary_op2) {
  58. return __init;
  59. }
  60. };
  61. } // namespace detail
  62. /// static version of std::inner_product
  63. template <std::size_t Size,
  64. class _InputIterator1, class _InputIterator2, class _Tp,
  65. class _BinaryOperation1, class _BinaryOperation2>
  66. BOOST_FORCEINLINE
  67. _Tp inner_product_k(_InputIterator1 __first1,
  68. _InputIterator2 __first2,
  69. _Tp __init,
  70. _BinaryOperation1 __binary_op1,
  71. _BinaryOperation2 __binary_op2) {
  72. return detail::inner_product_k_t<Size>::template apply(__first1,__first2,__init,
  73. __binary_op1, __binary_op2);
  74. }
  75. /// \brief 1D un-guarded correlation with a variable-size kernel
  76. template <typename PixelAccum,typename SrcIterator,typename KernelIterator,typename Integer,typename DstIterator>
  77. inline DstIterator correlate_pixels_n(SrcIterator src_begin,SrcIterator src_end,
  78. KernelIterator ker_begin,Integer ker_size,
  79. DstIterator dst_begin) {
  80. using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
  81. using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
  82. using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
  83. PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
  84. while(src_begin!=src_end) {
  85. pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
  86. std::inner_product(src_begin,src_begin+ker_size,ker_begin,acc_zero,
  87. pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
  88. pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
  89. *dst_begin);
  90. ++src_begin; ++dst_begin;
  91. }
  92. return dst_begin;
  93. }
  94. /// \brief 1D un-guarded correlation with a fixed-size kernel
  95. template <std::size_t Size,typename PixelAccum,typename SrcIterator,typename KernelIterator,typename DstIterator>
  96. inline DstIterator correlate_pixels_k(SrcIterator src_begin,SrcIterator src_end,
  97. KernelIterator ker_begin,
  98. DstIterator dst_begin) {
  99. using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
  100. using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
  101. using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
  102. PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
  103. while(src_begin!=src_end) {
  104. pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
  105. inner_product_k<Size>(src_begin,ker_begin,acc_zero,
  106. pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
  107. pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
  108. *dst_begin);
  109. ++src_begin; ++dst_begin;
  110. }
  111. return dst_begin;
  112. }
  113. /// \brief destination is set to be product of the source and a scalar
  114. template <typename PixelAccum,typename SrcView,typename Scalar,typename DstView>
  115. inline void view_multiplies_scalar(const SrcView& src,const Scalar& scalar,const DstView& dst) {
  116. BOOST_ASSERT(src.dimensions() == dst.dimensions());
  117. using PIXEL_SRC_REF = typename pixel_proxy<typename SrcView::value_type>::type;
  118. using PIXEL_DST_REF = typename pixel_proxy<typename DstView::value_type>::type;
  119. int height=src.height();
  120. for(int rr=0;rr<height;++rr) {
  121. typename SrcView::x_iterator it_src=src.row_begin(rr);
  122. typename DstView::x_iterator it_dst=dst.row_begin(rr);
  123. typename SrcView::x_iterator it_src_end=src.row_end(rr);
  124. while(it_src!=it_src_end) {
  125. pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
  126. pixel_multiplies_scalar_t<PIXEL_SRC_REF,Scalar,PixelAccum>()(*it_src,scalar),
  127. *it_dst);
  128. ++it_src; ++it_dst;
  129. }
  130. }
  131. }
  132. }} // namespace boost::gil
  133. #endif