summaryrefslogtreecommitdiff
path: root/boost/gil/extension/numeric/algorithm.hpp
blob: b7c175985f70e4b61d14a21ad0a1b41127fcd66f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
    Copyright 2005-2007 Adobe Systems Incorporated
   
    Use, modification and distribution are subject to the Boost Software License,
    Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    http://www.boost.org/LICENSE_1_0.txt).
*/

/*************************************************************************************************/

#ifndef BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP

/*!
/// \file               
/// \brief Numeric algorithms
/// \author Hailin Jin and Lubomir Bourdev \n
///         Adobe Systems Incorporated
/// \date   2005-2007 \n
*/

#include <cassert>
#include <iterator>
#include <algorithm>
#include <numeric>

#include <boost/gil/gil_config.hpp>
#include <boost/gil/pixel_iterator.hpp>
#include <boost/gil/metafunctions.hpp>

namespace boost { namespace gil {

/// \brief Returns the reference proxy associated with a type that has a \p "reference" member typedef.
///
/// The reference proxy is the reference type, but with stripped-out C++ reference. It models PixelConcept
template <typename T>
struct pixel_proxy : public remove_reference<typename T::reference> {};

/// \brief std::for_each for a pair of iterators
template <typename Iterator1,typename Iterator2,typename BinaryFunction>
BinaryFunction for_each(Iterator1 first1,Iterator1 last1,Iterator2 first2,BinaryFunction f) {
    while(first1!=last1)
        f(*first1++,*first2++);
    return f;
}

template <typename SrcIterator,typename DstIterator>
inline DstIterator assign_pixels(SrcIterator src,SrcIterator src_end,DstIterator dst) {
    for_each(src,src_end,dst,pixel_assigns_t<typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
                                             typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type>());             
    return dst+(src_end-src);
}

namespace detail {
template <std::size_t Size>
struct inner_product_k_t {
    template <class _InputIterator1, class _InputIterator2, class _Tp,
              class _BinaryOperation1, class _BinaryOperation2>
    static _Tp apply(_InputIterator1 __first1, 
                     _InputIterator2 __first2, _Tp __init, 
                     _BinaryOperation1 __binary_op1,
                     _BinaryOperation2 __binary_op2) {
        __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
        return inner_product_k_t<Size-1>::template apply(__first1+1,__first2+1,__init,
                                                         __binary_op1, __binary_op2);
    }
};

template <>
struct inner_product_k_t<0> {
    template <class _InputIterator1, class _InputIterator2, class _Tp,
              class _BinaryOperation1, class _BinaryOperation2>
    static _Tp apply(_InputIterator1 __first1, 
                     _InputIterator2 __first2, _Tp __init, 
                     _BinaryOperation1 __binary_op1,
                     _BinaryOperation2 __binary_op2) {
        return __init;
    }
};
} // namespace detail

/// static version of std::inner_product
template <std::size_t Size,
          class _InputIterator1, class _InputIterator2, class _Tp,
          class _BinaryOperation1, class _BinaryOperation2>
BOOST_FORCEINLINE
_Tp inner_product_k(_InputIterator1 __first1, 
                    _InputIterator2 __first2,
                    _Tp __init, 
                    _BinaryOperation1 __binary_op1,
                    _BinaryOperation2 __binary_op2) {
    return detail::inner_product_k_t<Size>::template apply(__first1,__first2,__init,
                                                           __binary_op1, __binary_op2);
}

/// \brief 1D un-guarded correlation with a variable-size kernel
template <typename PixelAccum,typename SrcIterator,typename KernelIterator,typename Integer,typename DstIterator>
inline DstIterator correlate_pixels_n(SrcIterator src_begin,SrcIterator src_end,
                                      KernelIterator ker_begin,Integer ker_size,
                                      DstIterator dst_begin) {
    typedef typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type PIXEL_SRC_REF;
    typedef typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type PIXEL_DST_REF;
    typedef typename std::iterator_traits<KernelIterator>::value_type kernel_type;
    PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
    while(src_begin!=src_end) {
        pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
            std::inner_product(src_begin,src_begin+ker_size,ker_begin,acc_zero,
                               pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
                               pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
            *dst_begin);
        ++src_begin; ++dst_begin;
    }
    return dst_begin;
}

/// \brief 1D un-guarded correlation with a fixed-size kernel
template <std::size_t Size,typename PixelAccum,typename SrcIterator,typename KernelIterator,typename DstIterator>
inline DstIterator correlate_pixels_k(SrcIterator src_begin,SrcIterator src_end,
                                      KernelIterator ker_begin,
                                      DstIterator dst_begin) {
    typedef typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type PIXEL_SRC_REF;
    typedef typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type PIXEL_DST_REF;
    typedef typename std::iterator_traits<KernelIterator>::value_type kernel_type;
    PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
    while(src_begin!=src_end) {
        pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
            inner_product_k<Size>(src_begin,ker_begin,acc_zero,
                                  pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
                                  pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
            *dst_begin);
        ++src_begin; ++dst_begin;
    }
    return dst_begin;
}

/// \brief destination is set to be product of the source and a scalar
template <typename PixelAccum,typename SrcView,typename Scalar,typename DstView>
inline void view_multiplies_scalar(const SrcView& src,const Scalar& scalar,const DstView& dst) {
    assert(src.dimensions()==dst.dimensions());
    typedef typename pixel_proxy<typename SrcView::value_type>::type PIXEL_SRC_REF;
    typedef typename pixel_proxy<typename DstView::value_type>::type PIXEL_DST_REF;
    int height=src.height();
    for(int rr=0;rr<height;++rr) {
        typename SrcView::x_iterator it_src=src.row_begin(rr);
        typename DstView::x_iterator it_dst=dst.row_begin(rr);
        typename SrcView::x_iterator it_src_end=src.row_end(rr);
        while(it_src!=it_src_end) {
            pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
                pixel_multiplies_scalar_t<PIXEL_SRC_REF,Scalar,PixelAccum>()(*it_src,scalar),
                *it_dst);
            ++it_src; ++it_dst;
        }
    }
}

} }  // namespace boost::gil

#endif // BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP