extend_by_projection.hpp 2.62 KB
Newer Older
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
#pragma once

#include <mln/core/image/view/adaptor.hpp>
#include <mln/core/range/view/transform.hpp>
#include <mln/core/private/traits/extension.hpp>

#include <range/v3/utility/common_type.hpp> // common_reference


namespace mln
{
  template <class I, class Proj>
  class extend_by_projection_view_base;


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

  template <class I, class Proj>
  class extend_by_projection_view_base : public image_adaptor<I>
  {
    using base_t = image_adaptor<I>;
    Proj m_proj;

  public:
    using extension_category = extension::custom_extension_tag;
    using reference          = const image_value_t<I>&; // Restrict the image to be read-only
    using category_type      = std::common_type_t<image_category_t<I>, bidirectional_image_tag>;
    using point_type         = image_point_t<I>;
    using typename image_adaptor<I>::domain_type;

Edwin Carlinet's avatar
Edwin Carlinet committed
33
    struct pixel_type : pixel_adaptor<image_pixel_t<I>>, mln::details::Pixel<pixel_type>
34
35
36
37
38
39
40
41
42
    {
      using reference = extend_by_projection_view_base<I, Proj>::reference;

      reference val() const
      {
        auto q = std::invoke(m_view->m_proj, this->base().point());
        return (*m_view)(q);
      }

Edwin Carlinet's avatar
Edwin Carlinet committed
43
44
      pixel_type(image_pixel_t<I> px, extend_by_projection_view_base<I, Proj>* ima)
        : pixel_type::pixel_adaptor{std::move(px)}
45
46
47
48
49
50
51
52
53
        , m_view{ima}
      {
      }

    private:
      extend_by_projection_view_base<I, Proj>* m_view;
    };

  public:
Baptiste Esteban's avatar
Baptiste Esteban committed
54
    extend_by_projection_view_base(I ima, Proj proj)
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
      : base_t{std::move(ima)}
      , m_proj{std::move(proj)}
    {
    }


    /// Accessible-image related methods
    /// \{
    template <class J = I>
    std::enable_if_t<image_accessible_v<J>, reference> operator()(point_type p)
    {
      assert(this->base().domain().has(p));
      return this->at(p);
    }

    template <class J = I>
    std::enable_if_t<image_accessible_v<J>, reference> at(point_type p)
    {
      auto q = std::invoke(m_proj, p);
      return this->base().at(q);
    }

    template <class J = I>
Edwin Carlinet's avatar
Edwin Carlinet committed
78
    std::enable_if_t<image_accessible_v<J>, pixel_type> pixel(point_type p)
79
80
    {
      assert(this->base().domain().has(p));
Edwin Carlinet's avatar
Edwin Carlinet committed
81
      return this->pixel_at(p);
82
83
84
    }

    template <class J = I>
Edwin Carlinet's avatar
Edwin Carlinet committed
85
    std::enable_if_t<image_accessible_v<J>, pixel_type> pixel_at(point_type p)
86
    {
Edwin Carlinet's avatar
Edwin Carlinet committed
87
      return {this->base().pixel_at(p), this};
88
89
90
91
92
    }
    /// \}

    auto pixels()
    {
Edwin Carlinet's avatar
Edwin Carlinet committed
93
      return ranges::view::transform(this->base().pixels(), [this](image_pixel_t<I> px) -> pixel_type {
94
95
96
97
98
99
        return {std::move(px), this};
      });
    }
  };

} // namespace mln