2 // Copyright 2005-2007 Adobe Systems Incorporated
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 #ifndef BOOST_GIL_PLANAR_PIXEL_REFERENCE_HPP
9 #define BOOST_GIL_PLANAR_PIXEL_REFERENCE_HPP
11 #include <boost/gil/channel.hpp>
12 #include <boost/gil/color_base.hpp>
13 #include <boost/gil/concepts.hpp>
14 #include <boost/gil/pixel.hpp>
15 #include <boost/gil/planar_pixel_iterator.hpp>
16 #include <boost/gil/detail/mp11.hpp>
18 #include <type_traits>
20 namespace boost { namespace gil {
22 /// \defgroup ColorBaseModelPlanarRef planar_pixel_reference
23 /// \ingroup ColorBaseModel
24 /// \brief A homogeneous color base whose element is a channel reference. Models HomogeneousColorBaseConcept, HomogeneousPixelConcept.
25 /// This class is used as a reference proxy to a planar pixel.
27 /// \defgroup PixelModelPlanarRef planar_pixel_reference
28 /// \ingroup PixelModel
29 /// \brief A reference proxy to a planar pixel. Models HomogeneousColorBaseConcept, HomogeneousPixelConcept.
31 /// \ingroup PixelModelPlanarRef ColorBaseModelPlanarRef PixelBasedModel
32 /// \brief A reference proxy to a planar pixel.
34 /// A reference to a planar pixel is a proxy class containing references to each of the corresponding channels.
35 /// Models: HomogeneousColorBaseConcept, HomogeneousPixelConcept
37 /// \tparam ChannelReference A channel reference, either const or mutable
38 /// \tparam ColorSpace
39 template <typename ChannelReference, typename ColorSpace>
40 struct planar_pixel_reference : detail::homogeneous_color_base
44 mp11::mp_size<ColorSpace>::value
47 using parent_t =detail::homogeneous_color_base
51 mp11::mp_size<ColorSpace>::value
55 // These three are only defined for homogeneous pixels
56 using channel_t = typename channel_traits<ChannelReference>::value_type;
57 using channel_const_reference = typename channel_traits<ChannelReference>::const_reference;
60 static constexpr bool is_mutable = channel_traits<ChannelReference>::is_mutable;
61 using value_type = pixel<channel_t,layout<ColorSpace>>;
62 using reference = planar_pixel_reference<ChannelReference, ColorSpace>;
63 using const_reference = planar_pixel_reference<channel_const_reference,ColorSpace>;
65 planar_pixel_reference(ChannelReference v0, ChannelReference v1)
69 planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2)
70 : parent_t(v0, v1, v2)
73 planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3)
74 : parent_t(v0, v1, v2, v3)
77 planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3, ChannelReference v4)
78 : parent_t(v0, v1, v2, v3, v4)
81 planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3, ChannelReference v4, ChannelReference v5)
82 : parent_t(v0, v1, v2, v3, v4, v5)
85 planar_pixel_reference(planar_pixel_reference const& p) : parent_t(p) {}
87 // TODO: What is the purpose of returning via const reference?
88 auto operator=(planar_pixel_reference const& p) const -> planar_pixel_reference const&
90 static_copy(p, *this);
94 template <typename Pixel>
95 planar_pixel_reference(Pixel const& p) : parent_t(p)
97 check_compatible<Pixel>();
100 // TODO: What is the purpose of returning via const reference?
101 template <typename Pixel>
102 auto operator=(Pixel const& p) const -> planar_pixel_reference const&
104 check_compatible<Pixel>();
105 static_copy(p, *this);
109 // PERFORMANCE_CHECK: Is this constructor necessary?
110 template <typename ChannelV, typename Mapping>
111 planar_pixel_reference(pixel<ChannelV, layout<ColorSpace, Mapping>>& p)
114 check_compatible<pixel<ChannelV, layout<ColorSpace, Mapping>>>();
117 // Construct at offset from a given location
118 template <typename ChannelPtr>
119 planar_pixel_reference(planar_pixel_iterator<ChannelPtr, ColorSpace> const& p, std::ptrdiff_t diff)
123 // This overload is necessary for a compiler implementing Core Issue 574
124 // to prevent generation of an implicit copy assignment operator (the reason
125 // for generating implicit copy assignment operator is that according to
126 // Core Issue 574, a cv-qualified assignment operator is not considered
127 // "copy assignment operator").
128 // EDG implemented Core Issue 574 starting with EDG Version 3.8. I'm not
129 // sure why they did it for a template member function as well.
130 #if BOOST_WORKAROUND(__HP_aCC, >= 61700) || BOOST_WORKAROUND(__INTEL_COMPILER, >= 1000)
131 const planar_pixel_reference& operator=(const planar_pixel_reference& p) { static_copy(p,*this); return *this; }
132 template <typename P> const planar_pixel_reference& operator=(const P& p) { check_compatible<P>(); static_copy(p,*this); return *this; }
135 template <typename Pixel>
136 bool operator==(Pixel const& p) const
138 check_compatible<Pixel>();
139 return static_equal(*this, p);
142 template <typename Pixel>
143 bool operator!=(Pixel const &p) const { return !(*this == p); }
145 auto operator[](std::size_t i) const -> ChannelReference { return this->at_c_dynamic(i); }
146 auto operator->() const -> planar_pixel_reference const* { return this; }
149 template <typename Pixel>
150 static void check_compatible()
152 gil_function_requires<PixelsCompatibleConcept<Pixel, planar_pixel_reference>>();
156 /////////////////////////////
158 /////////////////////////////
160 template <typename ChannelReference, typename ColorSpace, int K>
161 struct kth_element_type<planar_pixel_reference<ChannelReference, ColorSpace>, K>
163 using type = ChannelReference;
166 template <typename ChannelReference, typename ColorSpace, int K>
167 struct kth_element_reference_type
169 planar_pixel_reference<ChannelReference, ColorSpace>,
173 using type = ChannelReference;
176 template <typename ChannelReference, typename ColorSpace, int K>
177 struct kth_element_const_reference_type
179 planar_pixel_reference<ChannelReference, ColorSpace>,
182 : std::add_lvalue_reference<typename std::add_const<ChannelReference>::type>
184 // using type = typename channel_traits<ChannelReference>::const_reference;
187 /////////////////////////////
189 /////////////////////////////
191 /// \brief Metafunction predicate that flags planar_pixel_reference as a model of PixelConcept. Required by PixelConcept
192 /// \ingroup PixelModelPlanarRef
193 template <typename ChannelReference, typename ColorSpace>
194 struct is_pixel< planar_pixel_reference<ChannelReference, ColorSpace>>
198 /////////////////////////////
199 // HomogeneousPixelBasedConcept
200 /////////////////////////////
202 /// \brief Specifies the color space type of a planar pixel reference. Required by PixelBasedConcept
203 /// \ingroup PixelModelPlanarRef
204 template <typename ChannelReference, typename ColorSpace>
205 struct color_space_type<planar_pixel_reference<ChannelReference,ColorSpace> > {
206 using type = ColorSpace;
209 /// \brief Specifies the color space type of a planar pixel reference. Required by PixelBasedConcept
210 /// \ingroup PixelModelPlanarRef
211 template <typename ChannelReference, typename ColorSpace>
212 struct channel_mapping_type<planar_pixel_reference<ChannelReference,ColorSpace> > {
213 using type = typename layout<ColorSpace>::channel_mapping_t;
216 /// \brief Specifies that planar_pixel_reference represents a planar construct. Required by PixelBasedConcept
217 /// \ingroup PixelModelPlanarRef
218 template <typename ChannelReference, typename ColorSpace>
219 struct is_planar<planar_pixel_reference<ChannelReference, ColorSpace>>
223 /// \brief Specifies the color space type of a planar pixel reference. Required by HomogeneousPixelBasedConcept
224 /// \ingroup PixelModelPlanarRef
225 template <typename ChannelReference, typename ColorSpace>
226 struct channel_type<planar_pixel_reference<ChannelReference,ColorSpace> > {
227 using type = typename channel_traits<ChannelReference>::value_type;
230 }} // namespace boost::gil
233 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
234 // swap with 'left bias':
235 // - swap between proxy and anything
236 // - swap between value type and proxy
237 // - swap between proxy and proxy
238 // Having three overloads allows us to swap between different (but compatible) models of PixelConcept
240 /// \brief swap for planar_pixel_reference
241 /// \ingroup PixelModelPlanarRef
242 template <typename CR, typename CS, typename R> inline
243 void swap(const boost::gil::planar_pixel_reference<CR,CS> x, R& y) {
244 boost::gil::swap_proxy<typename boost::gil::planar_pixel_reference<CR,CS>::value_type>(x,y);
247 /// \brief swap for planar_pixel_reference
248 /// \ingroup PixelModelPlanarRef
249 template <typename CR, typename CS> inline
250 void swap(typename boost::gil::planar_pixel_reference<CR,CS>::value_type& x, const boost::gil::planar_pixel_reference<CR,CS> y) {
251 boost::gil::swap_proxy<typename boost::gil::planar_pixel_reference<CR,CS>::value_type>(x,y);
254 /// \brief swap for planar_pixel_reference
255 /// \ingroup PixelModelPlanarRef
256 template <typename CR, typename CS> inline
257 void swap(const boost::gil::planar_pixel_reference<CR,CS> x, const boost::gil::planar_pixel_reference<CR,CS> y) {
258 boost::gil::swap_proxy<typename boost::gil::planar_pixel_reference<CR,CS>::value_type>(x,y);