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