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_COLOR_BASE_HPP 9 #define BOOST_GIL_CONCEPTS_COLOR_BASE_HPP 10 11 #include <boost/gil/concepts/basic.hpp> 12 #include <boost/gil/concepts/color.hpp> 13 #include <boost/gil/concepts/concept_check.hpp> 14 #include <boost/gil/concepts/fwd.hpp> 15 16 #include <boost/core/ignore_unused.hpp> 17 #include <type_traits> 18 19 #if defined(BOOST_CLANG) 20 #pragma clang diagnostic push 21 #pragma clang diagnostic ignored "-Wunknown-pragmas" 22 #pragma clang diagnostic ignored "-Wunused-local-typedefs" 23 #endif 24 25 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900) 26 #pragma GCC diagnostic push 27 #pragma GCC diagnostic ignored "-Wunused-local-typedefs" 28 #endif 29 30 namespace boost { namespace gil { 31 32 // Forward declarations of at_c 33 namespace detail { 34 35 template <typename Element, typename Layout, int K> 36 struct homogeneous_color_base; 37 38 } // namespace detail 39 40 template <int K, typename E, typename L, int N> 41 auto at_c(detail::homogeneous_color_base<E, L, N>& p) 42 -> typename std::add_lvalue_reference<E>::type; 43 44 template <int K, typename E, typename L, int N> 45 auto at_c(detail::homogeneous_color_base<E, L, N> const& p) 46 -> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type; 47 48 template <typename P, typename C, typename L> 49 struct packed_pixel; 50 51 template <int K, typename P, typename C, typename L> 52 auto at_c(packed_pixel<P, C, L>& p) 53 -> typename kth_element_reference_type<packed_pixel<P, C, L>, K>::type; 54 55 template <int K, typename P, typename C, typename L> 56 auto at_c(packed_pixel<P, C, L> const& p) 57 -> typename kth_element_const_reference_type<packed_pixel<P, C, L>, K>::type; 58 59 template <typename B, typename C, typename L, bool M> 60 struct bit_aligned_pixel_reference; 61 62 template <int K, typename B, typename C, typename L, bool M> 63 inline auto at_c(bit_aligned_pixel_reference<B, C, L, M> const& p) 64 -> typename kth_element_reference_type 65 < 66 bit_aligned_pixel_reference<B, C, L, M>, 67 K 68 >::type; 69 70 // Forward declarations of semantic_at_c 71 template <int K, typename ColorBase> 72 auto semantic_at_c(ColorBase& p) 73 -> typename std::enable_if 74 < 75 !std::is_const<ColorBase>::value, 76 typename kth_semantic_element_reference_type<ColorBase, K>::type 77 >::type; 78 79 template <int K, typename ColorBase> 80 auto semantic_at_c(ColorBase const& p) 81 -> typename kth_semantic_element_const_reference_type<ColorBase, K>::type; 82 83 /// \ingroup ColorBaseConcept 84 /// \brief A color base is a container of color elements (such as channels, channel references or channel pointers). 85 /// 86 /// The most common use of color base is in the implementation of a pixel, 87 /// in which case the color elements are channel values. The color base concept, 88 /// however, can be used in other scenarios. For example, a planar pixel has 89 /// channels that are not contiguous in memory. Its reference is a proxy class 90 /// that uses a color base whose elements are channel references. Its iterator 91 /// uses a color base whose elements are channel iterators. 92 /// 93 /// A color base must have an associated layout (which consists of a color space, 94 /// as well as an ordering of the channels). 95 /// There are two ways to index the elements of a color base: A physical index 96 /// corresponds to the way they are ordered in memory, and a semantic index 97 /// corresponds to the way the elements are ordered in their color space. 98 /// For example, in the RGB color space the elements are ordered as 99 /// {red_t, green_t, blue_t}. For a color base with a BGR layout, the first element 100 /// in physical ordering is the blue element, whereas the first semantic element 101 /// is the red one. 102 /// Models of \p ColorBaseConcept are required to provide the \p at_c<K>(ColorBase) 103 /// function, which allows for accessing the elements based on their physical order. 104 /// GIL provides a \p semantic_at_c<K>(ColorBase) function (described later) 105 /// which can operate on any model of ColorBaseConcept and returns the corresponding 106 /// semantic element. 107 /// 108 /// \code 109 /// concept ColorBaseConcept<typename T> : CopyConstructible<T>, EqualityComparable<T> 110 /// { 111 /// // a GIL layout (the color space and element permutation) 112 /// typename layout_t; 113 /// 114 /// // The type of K-th element 115 /// template <int K> 116 /// struct kth_element_type; 117 /// where Metafunction<kth_element_type>; 118 /// 119 /// // The result of at_c 120 /// template <int K> 121 /// struct kth_element_const_reference_type; 122 /// where Metafunction<kth_element_const_reference_type>; 123 /// 124 /// template <int K> 125 /// kth_element_const_reference_type<T,K>::type at_c(T); 126 /// 127 /// // Copy-constructible and equality comparable with other compatible color bases 128 /// template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> } 129 /// T::T(T2); 130 /// template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> } 131 /// bool operator==(const T&, const T2&); 132 /// template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> } 133 /// bool operator!=(const T&, const T2&); 134 /// }; 135 /// \endcode 136 template <typename ColorBase> 137 struct ColorBaseConcept 138 { constraintsboost::gil::ColorBaseConcept139 void constraints() 140 { 141 gil_function_requires<CopyConstructible<ColorBase>>(); 142 gil_function_requires<EqualityComparable<ColorBase>>(); 143 144 using color_space_t = typename ColorBase::layout_t::color_space_t; 145 gil_function_requires<ColorSpaceConcept<color_space_t>>(); 146 147 using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t; 148 // TODO: channel_mapping_t must be an Boost.MP11-compatible random access sequence 149 150 static const int num_elements = size<ColorBase>::value; 151 152 using TN = typename kth_element_type<ColorBase, num_elements - 1>::type; 153 using RN = typename kth_element_const_reference_type<ColorBase, num_elements - 1>::type; 154 155 RN r = gil::at_c<num_elements - 1>(cb); 156 boost::ignore_unused(r); 157 158 // functions that work for every pixel (no need to require them) 159 semantic_at_c<0>(cb); 160 semantic_at_c<num_elements-1>(cb); 161 // also static_max(cb), static_min(cb), static_fill(cb,value), 162 // and all variations of static_for_each(), static_generate(), static_transform() 163 } 164 ColorBase cb; 165 }; 166 167 /// \ingroup ColorBaseConcept 168 /// \brief Color base which allows for modifying its elements 169 /// \code 170 /// concept MutableColorBaseConcept<ColorBaseConcept T> : Assignable<T>, Swappable<T> 171 /// { 172 /// template <int K> 173 /// struct kth_element_reference_type; where Metafunction<kth_element_reference_type>; 174 /// 175 /// template <int K> 176 /// kth_element_reference_type<kth_element_type<T,K>::type>::type at_c(T); 177 /// 178 /// template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> } 179 /// T& operator=(T&, const T2&); 180 /// }; 181 /// \endcode 182 template <typename ColorBase> 183 struct MutableColorBaseConcept 184 { constraintsboost::gil::MutableColorBaseConcept185 void constraints() 186 { 187 gil_function_requires<ColorBaseConcept<ColorBase>>(); 188 gil_function_requires<Assignable<ColorBase>>(); 189 gil_function_requires<Swappable<ColorBase>>(); 190 191 using R0 = typename kth_element_reference_type<ColorBase, 0>::type; 192 193 R0 r = gil::at_c<0>(cb); 194 gil::at_c<0>(cb) = r; 195 } 196 ColorBase cb; 197 }; 198 199 /// \ingroup ColorBaseConcept 200 /// \brief Color base that also has a default-constructor. Refines Regular 201 /// \code 202 /// concept ColorBaseValueConcept<typename T> : MutableColorBaseConcept<T>, Regular<T> 203 /// { 204 /// }; 205 /// \endcode 206 template <typename ColorBase> 207 struct ColorBaseValueConcept 208 { constraintsboost::gil::ColorBaseValueConcept209 void constraints() 210 { 211 gil_function_requires<MutableColorBaseConcept<ColorBase>>(); 212 gil_function_requires<Regular<ColorBase>>(); 213 } 214 }; 215 216 /// \ingroup ColorBaseConcept 217 /// \brief Color base whose elements all have the same type 218 /// \code 219 /// concept HomogeneousColorBaseConcept<ColorBaseConcept CB> 220 /// { 221 /// // For all K in [0 ... size<C1>::value-1): 222 /// // where SameType<kth_element_type<CB,K>::type, kth_element_type<CB,K+1>::type>; 223 /// kth_element_const_reference_type<CB,0>::type dynamic_at_c(CB const&, std::size_t n) const; 224 /// }; 225 /// \endcode 226 template <typename ColorBase> 227 struct HomogeneousColorBaseConcept 228 { constraintsboost::gil::HomogeneousColorBaseConcept229 void constraints() 230 { 231 gil_function_requires<ColorBaseConcept<ColorBase>>(); 232 233 static const int num_elements = size<ColorBase>::value; 234 235 using T0 = typename kth_element_type<ColorBase, 0>::type; 236 using TN = typename kth_element_type<ColorBase, num_elements - 1>::type; 237 238 static_assert(std::is_same<T0, TN>::value, ""); // better than nothing 239 240 using R0 = typename kth_element_const_reference_type<ColorBase, 0>::type; 241 R0 r = dynamic_at_c(cb, 0); 242 boost::ignore_unused(r); 243 } 244 ColorBase cb; 245 }; 246 247 /// \ingroup ColorBaseConcept 248 /// \brief Homogeneous color base that allows for modifying its elements 249 /// \code 250 /// concept MutableHomogeneousColorBaseConcept<ColorBaseConcept CB> 251 /// : HomogeneousColorBaseConcept<CB> 252 /// { 253 /// kth_element_reference_type<CB, 0>::type dynamic_at_c(CB&, std::size_t n); 254 /// }; 255 /// \endcode 256 template <typename ColorBase> 257 struct MutableHomogeneousColorBaseConcept 258 { constraintsboost::gil::MutableHomogeneousColorBaseConcept259 void constraints() 260 { 261 gil_function_requires<ColorBaseConcept<ColorBase>>(); 262 gil_function_requires<HomogeneousColorBaseConcept<ColorBase>>(); 263 using R0 = typename kth_element_reference_type<ColorBase, 0>::type; 264 R0 r = dynamic_at_c(cb, 0); 265 boost::ignore_unused(r); 266 dynamic_at_c(cb, 0) = dynamic_at_c(cb, 0); 267 } 268 ColorBase cb; 269 }; 270 271 /// \ingroup ColorBaseConcept 272 /// \brief Homogeneous color base that also has a default constructor. 273 /// Refines Regular. 274 /// 275 /// \code 276 /// concept HomogeneousColorBaseValueConcept<typename T> 277 /// : MutableHomogeneousColorBaseConcept<T>, Regular<T> 278 /// { 279 /// }; 280 /// \endcode 281 template <typename ColorBase> 282 struct HomogeneousColorBaseValueConcept 283 { constraintsboost::gil::HomogeneousColorBaseValueConcept284 void constraints() 285 { 286 gil_function_requires<MutableHomogeneousColorBaseConcept<ColorBase>>(); 287 gil_function_requires<Regular<ColorBase>>(); 288 } 289 }; 290 291 /// \ingroup ColorBaseConcept 292 /// \brief Two color bases are compatible if they have the same color space and their elements are compatible, semantic-pairwise. 293 /// \code 294 /// concept ColorBasesCompatibleConcept<ColorBaseConcept C1, ColorBaseConcept C2> 295 /// { 296 /// where SameType<C1::layout_t::color_space_t, C2::layout_t::color_space_t>; 297 /// // also, for all K in [0 ... size<C1>::value): 298 /// // where Convertible<kth_semantic_element_type<C1,K>::type, kth_semantic_element_type<C2,K>::type>; 299 /// // where Convertible<kth_semantic_element_type<C2,K>::type, kth_semantic_element_type<C1,K>::type>; 300 /// }; 301 /// \endcode 302 template <typename ColorBase1, typename ColorBase2> 303 struct ColorBasesCompatibleConcept 304 { constraintsboost::gil::ColorBasesCompatibleConcept305 void constraints() 306 { 307 static_assert(std::is_same 308 < 309 typename ColorBase1::layout_t::color_space_t, 310 typename ColorBase2::layout_t::color_space_t 311 >::value, ""); 312 313 // using e1 = typename kth_semantic_element_type<ColorBase1,0>::type; 314 // using e2 = typename kth_semantic_element_type<ColorBase2,0>::type; 315 // "e1 is convertible to e2" 316 } 317 }; 318 319 }} // namespace boost::gil 320 321 #if defined(BOOST_CLANG) 322 #pragma clang diagnostic pop 323 #endif 324 325 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900) 326 #pragma GCC diagnostic pop 327 #endif 328 329 #endif 330