1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 //
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
7 //
8 #ifndef BOOST_GIL_EXAMPLE_INTERLEAVED_REF_HPP
9 #define BOOST_GIL_EXAMPLE_INTERLEAVED_REF_HPP
10 
11 #include <boost/gil.hpp>
12 #include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
13 
14 #include <type_traits>
15 
16 // Example on how to create a new model of a pixel reference
17 
18 namespace boost { namespace gil {
19 
20 // A model of an interleaved pixel reference. Holds a pointer to the first channel
21 // MODELS:
22 //    MutableHomogeneousPixelConcept
23 //       MutableHomogeneousColorBaseConcept
24 //           MutableColorBaseConcept
25 //           HomogeneousColorBaseConcept
26 //               ColorBaseConcept
27 //    HomogeneousPixelBasedConcept
28 //       PixelBasedConcept
29 //
30 // For planar reference proxies to work properly, all of their methods must be const-qualified
31 // and their iterator's reference type must be const-qualified.
32 // Mutability of the reference proxy is part of its type (in this case, depends on the mutability of ChannelReference)
33 
34 /// \tparam ChannelReference - Models ChannelConcept.
35 ///         A channel reference, unsigned char& or const unsigned char&
36 /// \tparam Layout - A layout (includes the color space and channel ordering)
37 template <typename ChannelReference, typename Layout>
38 struct interleaved_ref
39 {
40 private:
41     using channel_t = typename channel_traits<ChannelReference>::value_type;
42     using channel_pointer_t = typename channel_traits<ChannelReference>::pointer;
43     using channel_reference_t = typename channel_traits<ChannelReference>::reference;
44     using channel_const_reference_t = typename channel_traits<ChannelReference>::const_reference;
45 
46 public:
47     using layout_t = Layout; // Required by ColorBaseConcept
48 
49     // Copy construction from a compatible type. The copy constructor of references is shallow. The channels themselves are not copied.
interleaved_refboost::gil::interleaved_ref50     interleaved_ref(const interleaved_ref& p) : _channels(p._channels) {}
interleaved_refboost::gil::interleaved_ref51     template <typename P> interleaved_ref(const P& p) : _channels(p._channels) { check_compatible<P>(); }
52 
operator ==boost::gil::interleaved_ref53     template <typename P> bool operator==(const P& p)    const { check_compatible<P>(); return static_equal(*this,p); }
operator !=boost::gil::interleaved_ref54     template <typename P> bool operator!=(const P& p)    const { return !(*this==p); }
55 
56 // Required by MutableColorBaseConcept
57 
58     // Assignment from a compatible type
operator =boost::gil::interleaved_ref59     const interleaved_ref&  operator=(const interleaved_ref& p)  const { static_copy(p,*this); return *this; }
operator =boost::gil::interleaved_ref60     template <typename P> const interleaved_ref& operator=(const P& p) const { check_compatible<P>(); static_copy(p,*this); return *this; }
61 
62 // Required by PixelConcept
63     using value_type = pixel<channel_t, layout_t>;
64     using reference = interleaved_ref;
65     using const_reference = interleaved_ref<channel_const_reference_t, layout_t>;
66     static const bool is_mutable = channel_traits<ChannelReference>::is_mutable;
67 
68 // Required by HomogeneousPixelConcept
operator []boost::gil::interleaved_ref69     ChannelReference                   operator[](std::size_t i) const { return _channels[i]; }
70 
71 // Custom constructor (not part of any concept)
interleaved_refboost::gil::interleaved_ref72     explicit interleaved_ref(channel_pointer_t channels) : _channels(channels) {}
73 // This is needed for the reference proxy to work properly
operator ->boost::gil::interleaved_ref74     const interleaved_ref*             operator->()              const { return this; }
75 private:
76     channel_pointer_t _channels;
77 
check_compatibleboost::gil::interleaved_ref78     template <typename Pixel> static void check_compatible() { gil_function_requires<PixelsCompatibleConcept<Pixel,interleaved_ref>>(); }
79 };
80 
81 // Required by ColorBaseConcept
82 template <typename ChannelReference, typename Layout, int K>
83 struct kth_element_type<interleaved_ref<ChannelReference, Layout>, K>
84 {
85     using type = ChannelReference;
86 };
87 
88 template <typename ChannelReference, typename Layout, int K>
89 struct kth_element_reference_type<interleaved_ref<ChannelReference, Layout>, K>
90 {
91     using type = ChannelReference;
92 };
93 
94 template <typename ChannelReference, typename Layout, int K>
95 struct kth_element_const_reference_type<interleaved_ref<ChannelReference, Layout>, K>
96 {
97     using type = ChannelReference;
98     // XXX: using type = typename channel_traits<ChannelReference>::const_reference;
99 };
100 
101 // Required by ColorBaseConcept
102 template <int K, typename ChannelReference, typename Layout>
103 typename element_reference_type<interleaved_ref<ChannelReference,Layout>>::type
at_c(const interleaved_ref<ChannelReference,Layout> & p)104 at_c(const interleaved_ref<ChannelReference,Layout>& p) { return p[K]; };
105 
106 // Required by HomogeneousColorBaseConcept
107 template <typename ChannelReference, typename Layout>
108 typename element_reference_type<interleaved_ref<ChannelReference,Layout>>::type
dynamic_at_c(const interleaved_ref<ChannelReference,Layout> & p,std::size_t n)109 dynamic_at_c(const interleaved_ref<ChannelReference,Layout>& p, std::size_t n) { return p[n]; };
110 
111 namespace detail {
112     struct swap_fn_t {
operator ()boost::gil::detail::swap_fn_t113         template <typename T> void operator()(T& x, T& y) const {
114             using std::swap;
115             swap(x,y);
116         }
117     };
118 }
119 
120 // Required by MutableColorBaseConcept. The default std::swap does not do the right thing for proxy references - it swaps the references, not the values
121 template <typename ChannelReference, typename Layout>
swap(const interleaved_ref<ChannelReference,Layout> & x,const interleaved_ref<ChannelReference,Layout> & y)122 void swap(const interleaved_ref<ChannelReference,Layout>& x, const interleaved_ref<ChannelReference,Layout>& y) {
123     static_for_each(x,y,detail::swap_fn_t());
124 };
125 
126 // Required by PixelConcept
127 template <typename ChannelReference, typename Layout>
128 struct is_pixel<interleaved_ref<ChannelReference,Layout>> : public std::true_type {};
129 
130 
131 // Required by PixelBasedConcept
132 template <typename ChannelReference, typename Layout>
133 struct color_space_type<interleaved_ref<ChannelReference, Layout>>
134 {
135     using type = typename Layout::color_space_t;
136 };
137 
138 // Required by PixelBasedConcept
139 template <typename ChannelReference, typename Layout>
140 struct channel_mapping_type<interleaved_ref<ChannelReference, Layout>>
141 {
142     using type = typename Layout::channel_mapping_t;
143 };
144 
145 // Required by PixelBasedConcept
146 template <typename ChannelReference, typename Layout>
147 struct is_planar<interleaved_ref<ChannelReference,Layout>> : std::false_type {};
148 
149 // Required by HomogeneousPixelBasedConcept
150 template <typename ChannelReference, typename Layout>
151 struct channel_type<interleaved_ref<ChannelReference, Layout>>
152 {
153     using type = typename channel_traits<ChannelReference>::value_type;
154 };
155 
156 } }  // namespace boost::gil
157 
158 #endif
159