liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// Distributed under 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_PLANAR_PIXEL_REFERENCE_HPP
#define BOOST_GIL_PLANAR_PIXEL_REFERENCE_HPP
 
#include <boost/gil/channel.hpp>
#include <boost/gil/color_base.hpp>
#include <boost/gil/concepts.hpp>
#include <boost/gil/pixel.hpp>
#include <boost/gil/planar_pixel_iterator.hpp>
#include <boost/gil/detail/mp11.hpp>
 
#include <type_traits>
 
namespace boost { namespace gil {
 
/// \defgroup ColorBaseModelPlanarRef planar_pixel_reference
/// \ingroup ColorBaseModel
/// \brief A homogeneous color base whose element is a channel reference. Models HomogeneousColorBaseConcept, HomogeneousPixelConcept.
/// This class is used as a reference proxy to a planar pixel.
 
/// \defgroup PixelModelPlanarRef planar_pixel_reference
/// \ingroup PixelModel
/// \brief A reference proxy to a planar pixel. Models HomogeneousColorBaseConcept, HomogeneousPixelConcept.
 
/// \ingroup PixelModelPlanarRef ColorBaseModelPlanarRef PixelBasedModel
/// \brief A reference proxy to a planar pixel.
///
/// A reference to a planar pixel is a proxy class containing references to each of the corresponding channels.
/// Models: HomogeneousColorBaseConcept, HomogeneousPixelConcept
///
/// \tparam ChannelReference A channel reference, either const or mutable
/// \tparam ColorSpace
template <typename ChannelReference, typename ColorSpace>
struct planar_pixel_reference : detail::homogeneous_color_base
    <
        ChannelReference,
        layout<ColorSpace>,
        mp11::mp_size<ColorSpace>::value
    >
{
    using parent_t =detail::homogeneous_color_base
        <
            ChannelReference,
            layout<ColorSpace>,
            mp11::mp_size<ColorSpace>::value
        >;
 
private:
    // These three are only defined for homogeneous pixels
    using channel_t = typename channel_traits<ChannelReference>::value_type;
    using channel_const_reference = typename channel_traits<ChannelReference>::const_reference;
 
public:
    static constexpr bool is_mutable = channel_traits<ChannelReference>::is_mutable;
    using value_type = pixel<channel_t,layout<ColorSpace>>;
    using reference = planar_pixel_reference<ChannelReference, ColorSpace>;
    using const_reference = planar_pixel_reference<channel_const_reference,ColorSpace>;
 
    planar_pixel_reference(ChannelReference v0, ChannelReference v1)
        : parent_t(v0, v1)
    {}
 
    planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2)
        : parent_t(v0, v1, v2)
    {}
 
    planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3)
        : parent_t(v0, v1, v2, v3)
    {}
 
    planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3, ChannelReference v4)
        : parent_t(v0, v1, v2, v3, v4)
    {}
 
    planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3, ChannelReference v4, ChannelReference v5)
        : parent_t(v0, v1, v2, v3, v4, v5)
    {}
 
    planar_pixel_reference(planar_pixel_reference const& p) : parent_t(p) {}
 
    // TODO: What is the purpose of returning via const reference?
    auto operator=(planar_pixel_reference const& p) const -> planar_pixel_reference const&
    {
        static_copy(p, *this);
        return *this;
    }
 
    template <typename Pixel>
    planar_pixel_reference(Pixel const& p) : parent_t(p)
    {
         check_compatible<Pixel>();
    }
 
    // TODO: What is the purpose of returning via const reference?
    template <typename Pixel>
    auto operator=(Pixel const& p) const -> planar_pixel_reference const&
    {
        check_compatible<Pixel>();
        static_copy(p, *this);
        return *this;
    }
 
    // PERFORMANCE_CHECK: Is this constructor necessary?
    template <typename ChannelV, typename Mapping>
    planar_pixel_reference(pixel<ChannelV, layout<ColorSpace, Mapping>>& p)
       : parent_t(p)
    {
        check_compatible<pixel<ChannelV, layout<ColorSpace, Mapping>>>();
    }
 
    // Construct at offset from a given location
    template <typename ChannelPtr>
    planar_pixel_reference(planar_pixel_iterator<ChannelPtr, ColorSpace> const& p, std::ptrdiff_t diff)
        : parent_t(p, diff)
    {}
 
// This overload is necessary for a compiler implementing Core Issue 574
// to prevent generation of an implicit copy assignment operator (the reason
// for generating implicit copy assignment operator is that according to
// Core Issue 574, a cv-qualified assignment operator is not considered
// "copy assignment operator").
// EDG implemented Core Issue 574 starting with EDG Version 3.8. I'm not
// sure why they did it for a template member function as well.
#if BOOST_WORKAROUND(__HP_aCC, >= 61700) || BOOST_WORKAROUND(__INTEL_COMPILER, >= 1000)
    const planar_pixel_reference& operator=(const planar_pixel_reference& p) { static_copy(p,*this); return *this; }
    template <typename P> const planar_pixel_reference& operator=(const P& p) { check_compatible<P>(); static_copy(p,*this); return *this; }
#endif
 
    template <typename Pixel>
    bool operator==(Pixel const& p) const
    {
        check_compatible<Pixel>();
        return static_equal(*this, p);
    }
 
    template <typename Pixel>
    bool operator!=(Pixel const &p) const { return !(*this == p); }
 
    auto operator[](std::size_t i) const -> ChannelReference { return this->at_c_dynamic(i); }
    auto operator->() const -> planar_pixel_reference const* { return this; }
 
private:
    template <typename Pixel>
    static void check_compatible()
    {
        gil_function_requires<PixelsCompatibleConcept<Pixel, planar_pixel_reference>>();
    }
};
 
/////////////////////////////
//  ColorBasedConcept
/////////////////////////////
 
template <typename ChannelReference, typename ColorSpace, int K>
struct kth_element_type<planar_pixel_reference<ChannelReference, ColorSpace>, K>
{
    using type = ChannelReference;
};
 
template <typename ChannelReference, typename ColorSpace, int K>
struct kth_element_reference_type
    <
        planar_pixel_reference<ChannelReference, ColorSpace>,
        K
    >
{
    using type = ChannelReference;
};
 
template <typename ChannelReference, typename ColorSpace, int K>
struct kth_element_const_reference_type
    <
        planar_pixel_reference<ChannelReference, ColorSpace>,
        K
    >
    : std::add_lvalue_reference<typename std::add_const<ChannelReference>::type>
{
    //    using type = typename channel_traits<ChannelReference>::const_reference;
};
 
/////////////////////////////
//  PixelConcept
/////////////////////////////
 
/// \brief Metafunction predicate that flags planar_pixel_reference as a model of PixelConcept. Required by PixelConcept
/// \ingroup PixelModelPlanarRef
template <typename ChannelReference, typename ColorSpace>
struct is_pixel< planar_pixel_reference<ChannelReference, ColorSpace>>
    : std::true_type
{};
 
/////////////////////////////
//  HomogeneousPixelBasedConcept
/////////////////////////////
 
/// \brief Specifies the color space type of a planar pixel reference. Required by PixelBasedConcept
/// \ingroup PixelModelPlanarRef
template <typename ChannelReference, typename ColorSpace>
struct color_space_type<planar_pixel_reference<ChannelReference,ColorSpace> > {
    using type = ColorSpace;
};
 
/// \brief Specifies the color space type of a planar pixel reference. Required by PixelBasedConcept
/// \ingroup PixelModelPlanarRef
template <typename ChannelReference, typename ColorSpace>
struct channel_mapping_type<planar_pixel_reference<ChannelReference,ColorSpace> > {
    using type = typename layout<ColorSpace>::channel_mapping_t;
};
 
/// \brief Specifies that planar_pixel_reference represents a planar construct. Required by PixelBasedConcept
/// \ingroup PixelModelPlanarRef
template <typename ChannelReference, typename ColorSpace>
struct is_planar<planar_pixel_reference<ChannelReference, ColorSpace>>
    : std::true_type
{};
 
/// \brief Specifies the color space type of a planar pixel reference. Required by HomogeneousPixelBasedConcept
/// \ingroup PixelModelPlanarRef
template <typename ChannelReference, typename ColorSpace>
struct channel_type<planar_pixel_reference<ChannelReference,ColorSpace> > {
    using type = typename channel_traits<ChannelReference>::value_type;
};
 
}}  // namespace boost::gil
 
namespace std {
// We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
// swap with 'left bias':
// - swap between proxy and anything
// - swap between value type and proxy
// - swap between proxy and proxy
// Having three overloads allows us to swap between different (but compatible) models of PixelConcept
 
/// \brief  swap for planar_pixel_reference
/// \ingroup PixelModelPlanarRef
template <typename CR, typename CS, typename R> inline
void swap(const boost::gil::planar_pixel_reference<CR,CS> x, R& y) {
    boost::gil::swap_proxy<typename boost::gil::planar_pixel_reference<CR,CS>::value_type>(x,y);
}
 
/// \brief  swap for planar_pixel_reference
/// \ingroup PixelModelPlanarRef
template <typename CR, typename CS> inline
void swap(typename boost::gil::planar_pixel_reference<CR,CS>::value_type& x, const boost::gil::planar_pixel_reference<CR,CS> y) {
    boost::gil::swap_proxy<typename boost::gil::planar_pixel_reference<CR,CS>::value_type>(x,y);
}
 
/// \brief  swap for planar_pixel_reference
/// \ingroup PixelModelPlanarRef
template <typename CR, typename CS> inline
void swap(const boost::gil::planar_pixel_reference<CR,CS> x, const boost::gil::planar_pixel_reference<CR,CS> y) {
    boost::gil::swap_proxy<typename boost::gil::planar_pixel_reference<CR,CS>::value_type>(x,y);
}
 
}   // namespace std
 
#endif