image_expr.hpp 12 KB
Newer Older
1
2
3
#ifndef MLN_CORE_IMAGE_IMAGE_EXPR_HPP
# define MLN_CORE_IMAGE_IMAGE_EXPR_HPP

Edwin Carlinet's avatar
Edwin Carlinet committed
4
5
# include <mln/core/functional.hpp>

6
7
8
9
# include <mln/core/concept/image.hpp>

# include <mln/core/image/zip_image.hpp>

10
11
# include <mln/core/range/iterator_range.hpp>
# include <mln/core/iterator/transform_iterator.hpp>
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# include <mln/core/iterator/transform_pixel_iterator.hpp>


namespace mln
{

  template <typename Expr>
  struct image_expr;

  template <typename UnaryFunction, typename Image>
  struct unary_image_expr;

  template <typename BinaryFunction, typename Image1, typename Image2>
  struct binary_image_expr;

  template <typename BinaryFunction, typename Image, typename Scalar>
  struct binary_image_scalar_expr;

  template <typename BinaryFunction, typename Scalar, typename Image>
  struct binary_scalar_image_expr;

Edwin Carlinet's avatar
Edwin Carlinet committed
33
34
35
  // template <typename UnaryFunction, typename I>
  // unary_image_expr<UnaryFunction, I>
  // make_unary_image_expr(I&& ima, UnaryFunction f);
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




  /*
  template <typename I>
  I& eval(Image<I>& ima);

  template <typename I>
  const I& eval(const Image<I>& ima);

  template <typename Expr>
  typename eval_type<Expr>::type
  eval(const image_expr<Expr>& ima)
  */


  /******************************************/
  /****          Implementation          ****/
  /******************************************/


  /******************************************/
  /****         Helper functions         ****/
  /******************************************/

  template <typename UnaryFunction, typename I>
  unary_image_expr<UnaryFunction, I>
Edwin Carlinet's avatar
Edwin Carlinet committed
64
  make_unary_image_expr(I&& ima, const UnaryFunction& f)
65
  {
Edwin Carlinet's avatar
Edwin Carlinet committed
66
    BOOST_CONCEPT_ASSERT((Image<typename std::decay<I>::type>));
67
68
69
70
71
    return unary_image_expr<UnaryFunction, I>(std::forward<I>(ima), f);
  }

  template <typename BinaryFunction, typename I1, typename I2>
  binary_image_expr<BinaryFunction, I1, I2>
Edwin Carlinet's avatar
Edwin Carlinet committed
72
  make_binary_image_expr(I1&& ima1, I2&& ima2, const BinaryFunction& f)
73
  {
Edwin Carlinet's avatar
Edwin Carlinet committed
74
75
    BOOST_CONCEPT_ASSERT((Image<typename std::decay<I1>::type>));
    BOOST_CONCEPT_ASSERT((Image<typename std::decay<I2>::type>));
76
77
78
79
80
    return binary_image_expr<BinaryFunction, I1, I2>(std::forward<I1>(ima1), std::forward<I2>(ima2), f);
  }

  template <typename BinaryFunction, typename I, typename Scalar>
  binary_image_scalar_expr<BinaryFunction, I, Scalar>
Edwin Carlinet's avatar
Edwin Carlinet committed
81
  make_binary_image_scalar_expr(I&& ima, const Scalar& x, const BinaryFunction& f)
82
  {
Edwin Carlinet's avatar
Edwin Carlinet committed
83
    BOOST_CONCEPT_ASSERT((Image<typename std::decay<I>::type>));
84
85
86
87
88
    return binary_image_scalar_expr<BinaryFunction, I, Scalar>(std::forward<I>(ima), x, f);
  }

  template <typename BinaryFunction, typename Scalar, typename I>
  binary_scalar_image_expr<BinaryFunction, Scalar, I>
Edwin Carlinet's avatar
Edwin Carlinet committed
89
  make_binary_scalar_image_expr(const Scalar& x, I&& ima, const BinaryFunction& f)
90
  {
Edwin Carlinet's avatar
Edwin Carlinet committed
91
    BOOST_CONCEPT_ASSERT((Image<typename std::decay<I>::type>));
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
    return binary_scalar_image_expr<BinaryFunction, Scalar, I>(x, std::forward<I>(ima), f);
  }



  /******************************************/
  /****              Traits              ****/
  /******************************************/


  template <typename UnaryFunction, typename Image>
  struct image_traits< unary_image_expr<UnaryFunction, Image> >
  {
    typedef typename image_traits<Image>::accessible accessible;
    typedef typename std::common_type< typename image_traits<Image>::category,
                                       bidirectional_image_tag >::type category;
  };

  template <typename BinaryFunction, typename Image1, typename Image2>
  struct image_traits< binary_image_expr<BinaryFunction, Image1, Image2> >
  {
    typedef typename std::integral_constant<bool,
                                            image_traits<Image1>::accessible::value and
                                            image_traits<Image2>::accessible::value >::type accessible;
    typedef typename std::common_type< typename image_traits<Image1>::category,
                                       typename image_traits<Image2>::category,
                                       bidirectional_image_tag >::type category;
  };

  template <typename BinaryFunction, typename Image, typename Scalar>
  struct image_traits< binary_image_scalar_expr<BinaryFunction, Image, Scalar> >
  {
    typedef typename image_traits<Image>::accessible accessible;
    typedef typename std::common_type< typename image_traits<Image>::category,
                                       bidirectional_image_tag >::type category;
  };

  template <typename BinaryFunction, typename Scalar, typename Image>
  struct image_traits< binary_scalar_image_expr<BinaryFunction, Scalar, Image> >
  {
    typedef typename image_traits<Image>::accessible accessible;
    typedef typename std::common_type< typename image_traits<Image>::category,
                                       bidirectional_image_tag >::type category;
  };




  template <typename Expr>
  struct image_expr : Image<Expr>
  {
    BOOST_CONCEPT_ASSERT((IterableImage<Expr>));
  };

  namespace internal
  {
148

149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

  template <typename UnaryFunction, typename Image, typename E>
  struct unary_image_expr_base : image_expr<E>
  {

  private:
    typedef E                                                           self_t;
    typedef typename std::remove_reference<Image>::type			image_t;

    typedef typename image_reference<image_t>::type                     arg_t;
    typedef typename image_const_reference<image_t>::type               const_arg_t;

    typedef typename image_value_iterator<image_t>::type                Vit;
    typedef typename image_pixel_iterator<image_t>::type                Pixit;
    typedef typename image_const_value_iterator<image_t>::type          ConstVit;
    typedef typename image_const_pixel_iterator<image_t>::type          ConstPixit;

167

168
169
170
171
  public:
    typedef typename image_t::point_type                                                        point_type;
    typedef typename image_t::point_type                                                        site_type;
    typedef typename image_t::domain_type                                                       domain_type;
172
    typedef typename std::result_of< const UnaryFunction(arg_t) >::type                         reference;
173
    typedef typename std::result_of< const UnaryFunction(const_arg_t) >::type                   const_reference;
174
    typedef typename std::remove_reference<reference>::type                                     value_type;
175

176
177
    typedef transform_iterator< Vit, UnaryFunction >                                            value_iterator;
    typedef transform_pixel_iterator<UnaryFunction, Pixit, E>                                     pixel_iterator;
178

179
180
    typedef transform_iterator< ConstVit, UnaryFunction>                                        const_value_iterator;
    typedef transform_pixel_iterator< UnaryFunction, ConstPixit, const E>                       const_pixel_iterator;
181
182
183
184

    //typedef typename const_value_iterator::reference::empty empty;
    //static_assert(std::is_const<typename std::remove_reference<typename const_value_iterator::reference>::type>::value, "");

185
186
    typedef transformed_pixel<UnaryFunction, Pixit, E>                                          pixel_type;
    typedef transformed_pixel<UnaryFunction, ConstPixit, const E>                               const_pixel_type;
187

188
189
190
191
    typedef iterator_range<value_iterator>                                               value_range;
    typedef iterator_range<pixel_iterator>                                               pixel_range;
    typedef iterator_range<const_value_iterator>                                         const_value_range;
    typedef iterator_range<const_pixel_iterator>                                         const_pixel_range;
192

Edwin Carlinet's avatar
Edwin Carlinet committed
193
    unary_image_expr_base(Image&& ima_, const UnaryFunction& f_):
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
      ima (std::forward<Image>(ima_)),
      f (f_)
    {
    }

    const domain_type&
    domain() const
    {
      return ima.domain();
    }

    template <typename dummy = void>
    typename std::enable_if< image_accessibility<self_t>::type::value, const_reference >::type
    operator() (point_type p) const
    {
      return f(ima(p));
    }

    template <typename dummy = void>
    typename std::enable_if< image_accessibility<self_t>::type::value, reference >::type
    operator() (point_type p)
    {
      return f(ima(p));
    }


    value_range
    values()
    {
223
224
      value_iterator x(ima.values().iter(), f);
      return make_iterator_range(x);
225
226
227
228
229
    }

    const_value_range
    values() const
    {
230
231
      const_value_iterator x(ima.values().iter(), f);
      return make_iterator_range(x);
232
233
234
235
236
237
    }


    pixel_range
    pixels()
    {
Edwin Carlinet's avatar
Edwin Carlinet committed
238
      pixel_iterator x(f, ima.pixels().iter(), exact(*this));
239
      return make_iterator_range(x);
240
241
242
243
244
    }

    const_pixel_range
    pixels() const
    {
Edwin Carlinet's avatar
Edwin Carlinet committed
245
      const_pixel_iterator x(f, ima.pixels().iter(), exact(*this));
246
      return make_iterator_range(x);
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    }

  private:
    Image	  ima;
    UnaryFunction f;
  };
  }

  namespace internal
  {

    template <typename Function, typename U, typename V>
    struct wrap_tuple_to_arg
    {
      typedef typename std::result_of<Function (U, V)>::type result_type;

Edwin Carlinet's avatar
Edwin Carlinet committed
263
264
265
266
      wrap_tuple_to_arg() = default;


      wrap_tuple_to_arg(const Function& f_)
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
        : f(f_)
      {
      }

      result_type
      operator() (boost::tuple<U,V> x) const
      {
        return f(boost::get<0>(x), boost::get<1>(x));
      }

    private:
      Function f;
    };

  }


  template <typename BinaryFunction, typename Image1, typename Image2>
  struct binary_image_expr :
    internal::unary_image_expr_base< internal::wrap_tuple_to_arg< BinaryFunction,
                                                                  typename image_reference<typename std::remove_reference<Image1>::type>::type,
                                                                  typename image_reference<typename std::remove_reference<Image2>::type>::type >,
                                     zip_image<Image1, Image2>,  binary_image_expr<BinaryFunction, Image1, Image2> >
  {
    typedef internal::wrap_tuple_to_arg< BinaryFunction,
                                          typename image_reference<typename std::remove_reference<Image1>::type>::type,
                                          typename image_reference<typename std::remove_reference<Image2>::type>::type > F;
    typedef internal::unary_image_expr_base< F, zip_image<Image1, Image2>,  binary_image_expr<BinaryFunction, Image1, Image2> > base_t;

  public:
Edwin Carlinet's avatar
Edwin Carlinet committed
297
    binary_image_expr(Image1&& ima1, Image2&& ima2, const BinaryFunction& f):
298
299
300
301
302
303
304
305
306
307
      base_t( imzip(std::forward<Image1>(ima1), std::forward<Image2>(ima2)), F(f) )
    {
    }
  };


  template <typename UnaryFunction, typename Image>
  struct unary_image_expr : internal::unary_image_expr_base< UnaryFunction, Image, unary_image_expr<UnaryFunction, Image> >
  {

Edwin Carlinet's avatar
Edwin Carlinet committed
308
    unary_image_expr(Image&& ima, const UnaryFunction& f):
309
310
311
312
313
314
315
316
      internal::unary_image_expr_base< UnaryFunction, Image, unary_image_expr<UnaryFunction, Image> >(std::forward<Image>(ima), f)
    {
    }
  };


  template <typename BinaryFunction, typename Image, typename Scalar>
  struct binary_image_scalar_expr :
Edwin Carlinet's avatar
Edwin Carlinet committed
317
    internal::unary_image_expr_base< mln::binder2nd<BinaryFunction, Scalar>, Image, binary_image_scalar_expr<BinaryFunction, Image, Scalar> >
318
319
  {
  private:
Edwin Carlinet's avatar
Edwin Carlinet committed
320
    typedef internal::unary_image_expr_base< mln::binder2nd<BinaryFunction, Scalar>, Image, binary_image_scalar_expr<BinaryFunction, Image, Scalar> > base_t;
321
322

  public:
Edwin Carlinet's avatar
Edwin Carlinet committed
323
324
    binary_image_scalar_expr(Image&& ima, const Scalar& x, const BinaryFunction& f):
      base_t(std::forward<Image>(ima), mln::bind2nd(f, x))
325
326
327
328
329
330
331
    {
    }
  };


  template <typename BinaryFunction, typename Scalar, typename Image>
  struct binary_scalar_image_expr
Edwin Carlinet's avatar
Edwin Carlinet committed
332
    : internal::unary_image_expr_base< mln::binder1st<BinaryFunction, Scalar>, Image, binary_scalar_image_expr<BinaryFunction,Scalar,Image> >
333
334
  {
  private:
Edwin Carlinet's avatar
Edwin Carlinet committed
335
    typedef internal::unary_image_expr_base< mln::binder1st<BinaryFunction, Scalar>, Image, binary_scalar_image_expr<BinaryFunction, Scalar, Image> > base_t;
336
337

  public:
Edwin Carlinet's avatar
Edwin Carlinet committed
338
339
    binary_scalar_image_expr(const Scalar& x, Image&& ima, const BinaryFunction& f):
      base_t(std::forward<Image>(ima), mln::bind1st(f, x))
340
341
342
343
344
345
346
347
348
349
    {
    }
  };




}

#endif // !MLN_CORE_IMAGE_IMAGE_EXPR_HPP