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_CONCEPTS_CHANNEL_HPP 9 #define BOOST_GIL_CONCEPTS_CHANNEL_HPP 10 11 #include <boost/gil/concepts/basic.hpp> 12 #include <boost/gil/concepts/concept_check.hpp> 13 #include <boost/gil/concepts/fwd.hpp> 14 15 #include <boost/concept_check.hpp> 16 17 #include <utility> // std::swap 18 #include <type_traits> 19 20 #if defined(BOOST_CLANG) 21 #pragma clang diagnostic push 22 #pragma clang diagnostic ignored "-Wunknown-pragmas" 23 #pragma clang diagnostic ignored "-Wunused-local-typedefs" 24 #endif 25 26 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900) 27 #pragma GCC diagnostic push 28 #pragma GCC diagnostic ignored "-Wunused-local-typedefs" 29 #endif 30 31 namespace boost { namespace gil { 32 33 // Forward declarations 34 template <typename T> 35 struct channel_traits; 36 37 template <typename DstT, typename SrcT> 38 auto channel_convert(SrcT const& val) 39 -> typename channel_traits<DstT>::value_type; 40 41 /// \ingroup ChannelConcept 42 /// \brief A channel is the building block of a color. 43 /// Color is defined as a mixture of primary colors and a channel defines 44 /// the degree to which each primary color is used in the mixture. 45 /// 46 /// For example, in the RGB color space, using 8-bit unsigned channels, 47 /// the color red is defined as [255 0 0], which means maximum of Red, 48 /// and no Green and Blue. 49 /// 50 /// Built-in scalar types, such as \p int and \p float, are valid GIL channels. 51 /// In more complex scenarios, channels may be represented as bit ranges or 52 /// even individual bits. 53 /// In such cases special classes are needed to represent the value and 54 /// reference to a channel. 55 /// 56 /// Channels have a traits class, \p channel_traits, which defines their 57 /// associated types as well as their operating ranges. 58 /// 59 /// \code 60 /// concept ChannelConcept<typename T> : EqualityComparable<T> 61 /// { 62 /// typename value_type = T; // use channel_traits<T>::value_type to access it 63 /// typename reference = T&; // use channel_traits<T>::reference to access it 64 /// typename pointer = T*; // use channel_traits<T>::pointer to access it 65 /// typename const_reference = const T&; // use channel_traits<T>::const_reference to access it 66 /// typename const_pointer = const T*; // use channel_traits<T>::const_pointer to access it 67 /// static const bool is_mutable; // use channel_traits<T>::is_mutable to access it 68 /// 69 /// static T min_value(); // use channel_traits<T>::min_value to access it 70 /// static T max_value(); // use channel_traits<T>::max_value to access it 71 /// }; 72 /// \endcode 73 template <typename T> 74 struct ChannelConcept 75 { constraintsboost::gil::ChannelConcept76 void constraints() 77 { 78 gil_function_requires<boost::EqualityComparableConcept<T>>(); 79 80 using v = typename channel_traits<T>::value_type; 81 using r = typename channel_traits<T>::reference; 82 using p = typename channel_traits<T>::pointer; 83 using cr = typename channel_traits<T>::const_reference; 84 using cp = typename channel_traits<T>::const_pointer; 85 86 channel_traits<T>::min_value(); 87 channel_traits<T>::max_value(); 88 } 89 90 T c; 91 }; 92 93 namespace detail 94 { 95 96 /// \tparam T models ChannelConcept 97 template <typename T> 98 struct ChannelIsMutableConcept 99 { constraintsboost::gil::detail::ChannelIsMutableConcept100 void constraints() 101 { 102 c1 = c2; 103 using std::swap; 104 swap(c1, c2); 105 } 106 T c1; 107 T c2; 108 }; 109 110 } // namespace detail 111 112 /// \brief A channel that allows for modifying its value 113 /// \code 114 /// concept MutableChannelConcept<ChannelConcept T> : Assignable<T>, Swappable<T> {}; 115 /// \endcode 116 /// \ingroup ChannelConcept 117 template <typename T> 118 struct MutableChannelConcept 119 { constraintsboost::gil::MutableChannelConcept120 void constraints() 121 { 122 gil_function_requires<ChannelConcept<T>>(); 123 gil_function_requires<detail::ChannelIsMutableConcept<T>>(); 124 } 125 }; 126 127 /// \brief A channel that supports default construction. 128 /// \code 129 /// concept ChannelValueConcept<ChannelConcept T> : Regular<T> {}; 130 /// \endcode 131 /// \ingroup ChannelConcept 132 template <typename T> 133 struct ChannelValueConcept 134 { constraintsboost::gil::ChannelValueConcept135 void constraints() 136 { 137 gil_function_requires<ChannelConcept<T>>(); 138 gil_function_requires<Regular<T>>(); 139 } 140 }; 141 142 /// \brief Predicate metafunction returning whether two channels are compatible 143 /// 144 /// Channels are considered compatible if their value types 145 /// (ignoring constness and references) are the same. 146 /// 147 /// Example: 148 /// 149 /// \code 150 /// static_assert(channels_are_compatible<uint8_t, const uint8_t&>::value, ""); 151 /// \endcode 152 /// \ingroup ChannelAlgorithm 153 template <typename T1, typename T2> // Models GIL Pixel 154 struct channels_are_compatible 155 : std::is_same 156 < 157 typename channel_traits<T1>::value_type, 158 typename channel_traits<T2>::value_type 159 > 160 { 161 }; 162 163 /// \brief Channels are compatible if their associated value types (ignoring constness and references) are the same 164 /// 165 /// \code 166 /// concept ChannelsCompatibleConcept<ChannelConcept T1, ChannelConcept T2> 167 /// { 168 /// where SameType<T1::value_type, T2::value_type>; 169 /// }; 170 /// \endcode 171 /// \ingroup ChannelConcept 172 template <typename Channel1, typename Channel2> 173 struct ChannelsCompatibleConcept 174 { constraintsboost::gil::ChannelsCompatibleConcept175 void constraints() 176 { 177 static_assert(channels_are_compatible<Channel1, Channel2>::value, ""); 178 } 179 }; 180 181 /// \brief A channel is convertible to another one if the \p channel_convert algorithm is defined for the two channels. 182 /// 183 /// Convertibility is non-symmetric and implies that one channel can be 184 /// converted to another. Conversion is explicit and often lossy operation. 185 /// 186 /// concept ChannelConvertibleConcept<ChannelConcept SrcChannel, ChannelValueConcept DstChannel> 187 /// { 188 /// DstChannel channel_convert(const SrcChannel&); 189 /// }; 190 /// \endcode 191 /// \ingroup ChannelConcept 192 template <typename SrcChannel, typename DstChannel> 193 struct ChannelConvertibleConcept 194 { constraintsboost::gil::ChannelConvertibleConcept195 void constraints() 196 { 197 gil_function_requires<ChannelConcept<SrcChannel>>(); 198 gil_function_requires<MutableChannelConcept<DstChannel>>(); 199 dst = channel_convert<DstChannel, SrcChannel>(src); 200 ignore_unused_variable_warning(dst); 201 } 202 SrcChannel src; 203 DstChannel dst; 204 }; 205 206 }} // namespace boost::gil 207 208 #if defined(BOOST_CLANG) 209 #pragma clang diagnostic pop 210 #endif 211 212 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900) 213 #pragma GCC diagnostic pop 214 #endif 215 216 #endif 217