algorithm.hpp 6.9 KB

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