1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // Copyright 2020 Samuel Debionne
4 //
5 // Distributed under the Boost Software License, Version 1.0
6 // See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt
8 //
9 #ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_HPP
10 #define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_HPP
11 
12 #include <boost/gil/extension/dynamic_image/any_image_view.hpp>
13 #include <boost/gil/extension/dynamic_image/apply_operation.hpp>
14 
15 #include <boost/gil/image.hpp>
16 #include <boost/gil/detail/mp11.hpp>
17 
18 #include <boost/config.hpp>
19 #include <boost/variant2/variant.hpp>
20 
21 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
22 #pragma warning(push)
23 #pragma warning(disable:4512) //assignment operator could not be generated
24 #endif
25 
26 namespace boost { namespace gil {
27 
28 namespace detail {
29 
30 template <typename T>
31 using get_view_t = typename T::view_t;
32 
33 template <typename Images>
34 using images_get_views_t = mp11::mp_transform<get_view_t, Images>;
35 
36 template <typename T>
37 using get_const_view_t = typename T::const_view_t;
38 
39 template <typename Images>
40 using images_get_const_views_t = mp11::mp_transform<get_const_view_t, Images>;
41 
42 struct recreate_image_fnobj
43 {
44     using result_type = void;
45     point<std::ptrdiff_t> const& _dimensions;
46     unsigned _alignment;
47 
recreate_image_fnobjboost::gil::detail::recreate_image_fnobj48     recreate_image_fnobj(point<std::ptrdiff_t> const& dims, unsigned alignment)
49         : _dimensions(dims), _alignment(alignment)
50     {}
51 
52     template <typename Image>
operator ()boost::gil::detail::recreate_image_fnobj53     result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); }
54 };
55 
56 template <typename AnyView>  // Models AnyViewConcept
57 struct any_image_get_view
58 {
59     using result_type = AnyView;
60     template <typename Image>
operator ()boost::gil::detail::any_image_get_view61     result_type operator()(Image& img) const
62     {
63         return result_type(view(img));
64     }
65 };
66 
67 template <typename AnyConstView>  // Models AnyConstViewConcept
68 struct any_image_get_const_view
69 {
70     using result_type = AnyConstView;
71     template <typename Image>
operator ()boost::gil::detail::any_image_get_const_view72     result_type operator()(Image const& img) const { return result_type{const_view(img)}; }
73 };
74 
75 } // namespce detail
76 
77 ////////////////////////////////////////////////////////////////////////////////////////
78 /// \ingroup ImageModel
79 /// \brief Represents a run-time specified image. Note it does NOT model ImageConcept
80 ///
81 /// Represents an image whose type (color space, layout, planar/interleaved organization, etc) can be specified at run time.
82 /// It is the runtime equivalent of \p image.
83 /// Some of the requirements of ImageConcept, such as the \p value_type alias cannot be fulfilled, since the language does not allow runtime type specification.
84 /// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image does not fully model ImageConcept.
85 /// In particular, its \p view and \p const_view methods return \p any_image_view, which does not fully model ImageViewConcept. See \p any_image_view for more.
86 ////////////////////////////////////////////////////////////////////////////////////////
87 
88 template <typename ...Images>
89 class any_image : public variant2::variant<Images...>
90 {
91     using parent_t = variant2::variant<Images...>;
92 public:
93     using view_t = mp11::mp_rename<detail::images_get_views_t<any_image>, any_image_view>;
94     using const_view_t = mp11::mp_rename<detail::images_get_const_views_t<any_image>, any_image_view>;
95     using x_coord_t = std::ptrdiff_t;
96     using y_coord_t = std::ptrdiff_t;
97     using point_t = point<std::ptrdiff_t>;
98 
99     any_image() = default;
any_image(any_image const & img)100     any_image(any_image const& img) : parent_t((parent_t const&)img) {}
101 
102     template <typename Image>
any_image(Image const & img)103     explicit any_image(Image const& img) : parent_t(img) {}
104 
105     template <typename Image>
any_image(Image && img)106     any_image(Image&& img) : parent_t(std::move(img)) {}
107 
108     template <typename Image>
any_image(Image & img,bool do_swap)109     explicit any_image(Image& img, bool do_swap) : parent_t(img, do_swap) {}
110 
111     template <typename ...OtherImages>
any_image(any_image<OtherImages...> const & img)112     any_image(any_image<OtherImages...> const& img)
113         : parent_t((variant2::variant<OtherImages...> const&)img)
114     {}
115 
operator =(any_image const & img)116     any_image& operator=(any_image const& img)
117     {
118         parent_t::operator=((parent_t const&)img);
119         return *this;
120     }
121 
122     template <typename Image>
operator =(Image const & img)123     any_image& operator=(Image const& img)
124     {
125         parent_t::operator=(img);
126         return *this;
127     }
128 
129     template <typename ...OtherImages>
operator =(any_image<OtherImages...> const & img)130     any_image& operator=(any_image<OtherImages...> const& img)
131     {
132             parent_t::operator=((typename variant2::variant<OtherImages...> const&)img);
133             return *this;
134     }
135 
recreate(const point_t & dims,unsigned alignment=1)136     void recreate(const point_t& dims, unsigned alignment=1)
137     {
138         apply_operation(*this, detail::recreate_image_fnobj(dims, alignment));
139     }
140 
recreate(x_coord_t width,y_coord_t height,unsigned alignment=1)141     void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1)
142     {
143         recreate({ width, height }, alignment);
144     }
145 
num_channels() const146     std::size_t num_channels() const
147     {
148         return apply_operation(*this, detail::any_type_get_num_channels());
149     }
150 
dimensions() const151     point_t dimensions() const
152     {
153         return apply_operation(*this, detail::any_type_get_dimensions());
154     }
155 
width() const156     x_coord_t width()  const { return dimensions().x; }
height() const157     y_coord_t height() const { return dimensions().y; }
158 };
159 
160 ///@{
161 /// \name view, const_view
162 /// \brief Get an image view from a run-time instantiated image
163 
164 /// \ingroup ImageModel
165 
166 /// \brief Returns the non-constant-pixel view of any image. The returned view is any view.
167 /// \tparam Images Models ImageVectorConcept
168 template <typename ...Images>
169 BOOST_FORCEINLINE
view(any_image<Images...> & img)170 auto view(any_image<Images...>& img) -> typename any_image<Images...>::view_t
171 {
172     using view_t = typename any_image<Images...>::view_t;
173     return apply_operation(img, detail::any_image_get_view<view_t>());
174 }
175 
176 /// \brief Returns the constant-pixel view of any image. The returned view is any view.
177 /// \tparam Types Models ImageVectorConcept
178 template <typename ...Images>
179 BOOST_FORCEINLINE
const_view(any_image<Images...> const & img)180 auto const_view(any_image<Images...> const& img) -> typename any_image<Images...>::const_view_t
181 {
182     using view_t = typename any_image<Images...>::const_view_t;
183     return apply_operation(img, detail::any_image_get_const_view<view_t>());
184 }
185 ///@}
186 
187 }}  // namespace boost::gil
188 
189 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
190 #pragma warning(pop)
191 #endif
192 
193 #endif
194