color_base.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. //
  2. // Copyright 2005-2007 Adobe Systems Incorporated
  3. // Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
  4. //
  5. // Distributed under the Boost Software License, Version 1.0
  6. // See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt
  8. //
  9. #ifndef BOOST_GIL_COLOR_BASE_HPP
  10. #define BOOST_GIL_COLOR_BASE_HPP
  11. #include <boost/gil/utilities.hpp>
  12. #include <boost/gil/concepts.hpp>
  13. #include <boost/gil/detail/mp11.hpp>
  14. #include <boost/assert.hpp>
  15. #include <boost/config.hpp>
  16. #include <type_traits>
  17. namespace boost { namespace gil {
  18. // Forward-declare
  19. template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff);
  20. // Forward-declare semantic_at_c
  21. template <int K, typename ColorBase>
  22. auto semantic_at_c(ColorBase& p)
  23. -> typename std::enable_if
  24. <
  25. !std::is_const<ColorBase>::value,
  26. typename kth_semantic_element_reference_type<ColorBase, K>::type
  27. >::type;
  28. template <int K, typename ColorBase>
  29. typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p);
  30. // Forward declare element_reference_type
  31. template <typename ColorBase> struct element_reference_type;
  32. template <typename ColorBase> struct element_const_reference_type;
  33. template <typename ColorBase, int K> struct kth_element_type;
  34. template <typename ColorBase, int K> struct kth_element_type<const ColorBase,K> : public kth_element_type<ColorBase,K> {};
  35. template <typename ColorBase, int K> struct kth_element_reference_type;
  36. template <typename ColorBase, int K> struct kth_element_reference_type<const ColorBase,K> : public kth_element_reference_type<ColorBase,K> {};
  37. template <typename ColorBase, int K> struct kth_element_const_reference_type;
  38. template <typename ColorBase, int K> struct kth_element_const_reference_type<const ColorBase,K> : public kth_element_const_reference_type<ColorBase,K> {};
  39. namespace detail {
  40. template <typename DstLayout, typename SrcLayout, int K>
  41. struct mapping_transform : mp11::mp_at
  42. <
  43. typename SrcLayout::channel_mapping_t,
  44. typename detail::type_to_index
  45. <
  46. typename DstLayout::channel_mapping_t,
  47. std::integral_constant<int, K>
  48. >
  49. >::type
  50. {};
  51. /// \defgroup ColorBaseModelHomogeneous detail::homogeneous_color_base
  52. /// \ingroup ColorBaseModel
  53. /// \brief A homogeneous color base holding one color element.
  54. /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
  55. /// If the element type models Regular, this class models HomogeneousColorBaseValueConcept.
  56. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  57. #pragma warning(push)
  58. #pragma warning(disable:4512) //assignment operator could not be generated
  59. #endif
  60. /// \brief A homogeneous color base holding one color element.
  61. /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
  62. /// \ingroup ColorBaseModelHomogeneous
  63. template <typename Element, typename Layout>
  64. struct homogeneous_color_base<Element, Layout, 1>
  65. {
  66. using layout_t = Layout;
  67. homogeneous_color_base() = default;
  68. homogeneous_color_base(Element v) : v0_(v) {}
  69. template <typename E2, typename L2>
  70. homogeneous_color_base(homogeneous_color_base<E2, L2, 1> const& c)
  71. : v0_(gil::at_c<0>(c))
  72. {}
  73. auto at(std::integral_constant<int, 0>)
  74. -> typename element_reference_type<homogeneous_color_base>::type
  75. { return v0_; }
  76. auto at(std::integral_constant<int, 0>) const
  77. -> typename element_const_reference_type<homogeneous_color_base>::type
  78. { return v0_; }
  79. // grayscale pixel values are convertible to channel type
  80. // FIXME: explicit?
  81. operator Element() const { return v0_; }
  82. private:
  83. Element v0_{};
  84. };
  85. /// \brief A homogeneous color base holding two color elements
  86. /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
  87. /// \ingroup ColorBaseModelHomogeneous
  88. template <typename Element, typename Layout>
  89. struct homogeneous_color_base<Element, Layout, 2>
  90. {
  91. using layout_t = Layout;
  92. homogeneous_color_base() = default;
  93. explicit homogeneous_color_base(Element v) : v0_(v), v1_(v) {}
  94. homogeneous_color_base(Element v0, Element v1) : v0_(v0), v1_(v1) {}
  95. template <typename E2, typename L2>
  96. homogeneous_color_base(homogeneous_color_base<E2, L2, 2> const& c)
  97. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  98. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  99. {}
  100. // Support for l-value reference proxy copy construction
  101. template <typename E2, typename L2>
  102. homogeneous_color_base(homogeneous_color_base<E2, L2, 2>& c)
  103. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  104. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  105. {}
  106. // Support for planar_pixel_iterator construction and dereferencing
  107. template <typename P>
  108. homogeneous_color_base(P* p, bool)
  109. : v0_(&semantic_at_c<0>(*p))
  110. , v1_(&semantic_at_c<1>(*p))
  111. {}
  112. // Support for planar_pixel_reference offset constructor
  113. template <typename Ptr>
  114. homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
  115. : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
  116. , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
  117. {}
  118. template <typename Ref>
  119. Ref deref() const
  120. {
  121. return Ref(*semantic_at_c<0>(*this), *semantic_at_c<1>(*this));
  122. }
  123. auto at(std::integral_constant<int, 0>)
  124. -> typename element_reference_type<homogeneous_color_base>::type
  125. { return v0_; }
  126. auto at(std::integral_constant<int, 0>) const
  127. -> typename element_const_reference_type<homogeneous_color_base>::type
  128. { return v0_; }
  129. auto at(std::integral_constant<int, 1>)
  130. -> typename element_reference_type<homogeneous_color_base>::type
  131. { return v1_; }
  132. auto at(std::integral_constant<int, 1>) const
  133. -> typename element_const_reference_type<homogeneous_color_base>::type
  134. { return v1_; }
  135. // Support for planar_pixel_reference operator[]
  136. Element at_c_dynamic(std::size_t i) const
  137. {
  138. if (i == 0)
  139. return v0_;
  140. else
  141. return v1_;
  142. }
  143. private:
  144. Element v0_{};
  145. Element v1_{};
  146. };
  147. /// \brief A homogeneous color base holding three color elements.
  148. /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
  149. /// \ingroup ColorBaseModelHomogeneous
  150. template <typename Element, typename Layout>
  151. struct homogeneous_color_base<Element, Layout, 3>
  152. {
  153. using layout_t = Layout;
  154. homogeneous_color_base() = default;
  155. explicit homogeneous_color_base(Element v) : v0_(v), v1_(v), v2_(v) {}
  156. homogeneous_color_base(Element v0, Element v1, Element v2)
  157. : v0_(v0), v1_(v1), v2_(v2)
  158. {}
  159. template <typename E2, typename L2>
  160. homogeneous_color_base(homogeneous_color_base<E2, L2, 3> const& c)
  161. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  162. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  163. , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
  164. {}
  165. // Support for l-value reference proxy copy construction
  166. template <typename E2, typename L2>
  167. homogeneous_color_base(homogeneous_color_base<E2, L2, 3>& c)
  168. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  169. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  170. , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
  171. {}
  172. // Support for planar_pixel_iterator construction and dereferencing
  173. template <typename P>
  174. homogeneous_color_base(P* p, bool)
  175. : v0_(&semantic_at_c<0>(*p))
  176. , v1_(&semantic_at_c<1>(*p))
  177. , v2_(&semantic_at_c<2>(*p))
  178. {}
  179. // Support for planar_pixel_reference offset constructor
  180. template <typename Ptr>
  181. homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
  182. : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
  183. , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
  184. , v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff))
  185. {}
  186. template <typename Ref>
  187. Ref deref() const
  188. {
  189. return Ref(
  190. *semantic_at_c<0>(*this),
  191. *semantic_at_c<1>(*this),
  192. *semantic_at_c<2>(*this));
  193. }
  194. auto at(std::integral_constant<int, 0>)
  195. -> typename element_reference_type<homogeneous_color_base>::type
  196. { return v0_; }
  197. auto at(std::integral_constant<int, 0>) const
  198. -> typename element_const_reference_type<homogeneous_color_base>::type
  199. { return v0_; }
  200. auto at(std::integral_constant<int, 1>)
  201. -> typename element_reference_type<homogeneous_color_base>::type
  202. { return v1_; }
  203. auto at(std::integral_constant<int, 1>) const
  204. -> typename element_const_reference_type<homogeneous_color_base>::type
  205. { return v1_; }
  206. auto at(std::integral_constant<int, 2>)
  207. -> typename element_reference_type<homogeneous_color_base>::type
  208. { return v2_; }
  209. auto at(std::integral_constant<int, 2>) const
  210. -> typename element_const_reference_type<homogeneous_color_base>::type
  211. { return v2_; }
  212. // Support for planar_pixel_reference operator[]
  213. Element at_c_dynamic(std::size_t i) const
  214. {
  215. switch (i)
  216. {
  217. case 0: return v0_;
  218. case 1: return v1_;
  219. }
  220. return v2_;
  221. }
  222. private:
  223. Element v0_{};
  224. Element v1_{};
  225. Element v2_{};
  226. };
  227. /// \brief A homogeneous color base holding four color elements.
  228. /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
  229. /// \ingroup ColorBaseModelHomogeneous
  230. template <typename Element, typename Layout>
  231. struct homogeneous_color_base<Element, Layout, 4>
  232. {
  233. using layout_t = Layout;
  234. homogeneous_color_base() = default;
  235. explicit homogeneous_color_base(Element v) : v0_(v), v1_(v), v2_(v), v3_(v) {}
  236. homogeneous_color_base(Element v0, Element v1, Element v2, Element v3)
  237. : v0_(v0), v1_(v1), v2_(v2), v3_(v3)
  238. {}
  239. template <typename E2, typename L2>
  240. homogeneous_color_base(homogeneous_color_base<E2, L2, 4> const& c)
  241. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  242. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  243. , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
  244. , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
  245. {}
  246. // Support for l-value reference proxy copy construction
  247. template <typename E2, typename L2>
  248. homogeneous_color_base(homogeneous_color_base<E2, L2, 4>& c)
  249. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  250. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  251. , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
  252. , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
  253. {}
  254. // Support for planar_pixel_iterator construction and dereferencing
  255. template <typename P>
  256. homogeneous_color_base(P * p, bool)
  257. : v0_(&semantic_at_c<0>(*p))
  258. , v1_(&semantic_at_c<1>(*p))
  259. , v2_(&semantic_at_c<2>(*p))
  260. , v3_(&semantic_at_c<3>(*p))
  261. {}
  262. // Support for planar_pixel_reference offset constructor
  263. template <typename Ptr>
  264. homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
  265. : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
  266. , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
  267. , v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff))
  268. , v3_(*memunit_advanced(semantic_at_c<3>(ptr), diff))
  269. {}
  270. template <typename Ref>
  271. Ref deref() const
  272. {
  273. return Ref(
  274. *semantic_at_c<0>(*this),
  275. *semantic_at_c<1>(*this),
  276. *semantic_at_c<2>(*this),
  277. *semantic_at_c<3>(*this));
  278. }
  279. auto at(std::integral_constant<int, 0>)
  280. -> typename element_reference_type<homogeneous_color_base>::type
  281. { return v0_; }
  282. auto at(std::integral_constant<int, 0>) const
  283. -> typename element_const_reference_type<homogeneous_color_base>::type
  284. { return v0_; }
  285. auto at(std::integral_constant<int, 1>)
  286. -> typename element_reference_type<homogeneous_color_base>::type
  287. { return v1_; }
  288. auto at(std::integral_constant<int, 1>) const
  289. -> typename element_const_reference_type<homogeneous_color_base>::type
  290. { return v1_; }
  291. auto at(std::integral_constant<int, 2>)
  292. -> typename element_reference_type<homogeneous_color_base>::type
  293. { return v2_; }
  294. auto at(std::integral_constant<int, 2>) const
  295. -> typename element_const_reference_type<homogeneous_color_base>::type
  296. { return v2_; }
  297. auto at(std::integral_constant<int, 3>)
  298. -> typename element_reference_type<homogeneous_color_base>::type
  299. { return v3_; }
  300. auto at(std::integral_constant<int, 3>) const
  301. -> typename element_const_reference_type<homogeneous_color_base>::type
  302. { return v3_; }
  303. // Support for planar_pixel_reference operator[]
  304. Element at_c_dynamic(std::size_t i) const
  305. {
  306. switch (i)
  307. {
  308. case 0: return v0_;
  309. case 1: return v1_;
  310. case 2: return v2_;
  311. }
  312. return v3_;
  313. }
  314. private:
  315. Element v0_{};
  316. Element v1_{};
  317. Element v2_{};
  318. Element v3_{};
  319. };
  320. /// \brief A homogeneous color base holding five color elements.
  321. /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
  322. /// \ingroup ColorBaseModelHomogeneous
  323. template <typename Element, typename Layout>
  324. struct homogeneous_color_base<Element, Layout, 5>
  325. {
  326. using layout_t = Layout;
  327. homogeneous_color_base() = default;
  328. explicit homogeneous_color_base(Element v)
  329. : v0_(v), v1_(v), v2_(v), v3_(v), v4_(v)
  330. {}
  331. homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4)
  332. : v0_(v0), v1_(v1), v2_(v2), v3_(v3), v4_(v4)
  333. {}
  334. template <typename E2, typename L2>
  335. homogeneous_color_base(homogeneous_color_base<E2, L2, 5> const& c)
  336. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  337. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  338. , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
  339. , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
  340. , v4_(gil::at_c<mapping_transform<Layout, L2, 4>::value>(c))
  341. {}
  342. // Support for l-value reference proxy copy construction
  343. template <typename E2, typename L2>
  344. homogeneous_color_base(homogeneous_color_base<E2, L2, 5>& c)
  345. : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
  346. , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
  347. , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
  348. , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
  349. , v4_(gil::at_c<mapping_transform<Layout, L2, 4>::value>(c))
  350. {}
  351. // Support for planar_pixel_iterator construction and dereferencing
  352. template <typename P>
  353. homogeneous_color_base(P* p, bool)
  354. : v0_(&semantic_at_c<0>(*p))
  355. , v1_(&semantic_at_c<1>(*p))
  356. , v2_(&semantic_at_c<2>(*p))
  357. , v3_(&semantic_at_c<3>(*p))
  358. , v4_(&semantic_at_c<4>(*p))
  359. {}
  360. // Support for planar_pixel_reference offset constructor
  361. template <typename Ptr>
  362. homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
  363. : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
  364. , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
  365. , v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff))
  366. , v3_(*memunit_advanced(semantic_at_c<3>(ptr), diff))
  367. , v4_(*memunit_advanced(semantic_at_c<4>(ptr), diff))
  368. {}
  369. auto at(std::integral_constant<int, 0>)
  370. -> typename element_reference_type<homogeneous_color_base>::type
  371. { return v0_; }
  372. auto at(std::integral_constant<int, 0>) const
  373. -> typename element_const_reference_type<homogeneous_color_base>::type
  374. { return v0_; }
  375. auto at(std::integral_constant<int, 1>)
  376. -> typename element_reference_type<homogeneous_color_base>::type
  377. { return v1_; }
  378. auto at(std::integral_constant<int, 1>) const
  379. -> typename element_const_reference_type<homogeneous_color_base>::type
  380. { return v1_; }
  381. auto at(std::integral_constant<int, 2>)
  382. -> typename element_reference_type<homogeneous_color_base>::type
  383. { return v2_; }
  384. auto at(std::integral_constant<int, 2>) const
  385. -> typename element_const_reference_type<homogeneous_color_base>::type
  386. { return v2_; }
  387. auto at(std::integral_constant<int, 3>)
  388. -> typename element_reference_type<homogeneous_color_base>::type
  389. { return v3_; }
  390. auto at(std::integral_constant<int, 3>) const
  391. -> typename element_const_reference_type<homogeneous_color_base>::type
  392. { return v3_; }
  393. auto at(std::integral_constant<int, 4>)
  394. -> typename element_reference_type<homogeneous_color_base>::type
  395. { return v4_; }
  396. auto at(std::integral_constant<int, 4>) const
  397. -> typename element_const_reference_type<homogeneous_color_base>::type
  398. { return v4_; }
  399. template <typename Ref>
  400. Ref deref() const
  401. {
  402. return Ref(
  403. *semantic_at_c<0>(*this),
  404. *semantic_at_c<1>(*this),
  405. *semantic_at_c<2>(*this),
  406. *semantic_at_c<3>(*this),
  407. *semantic_at_c<4>(*this));
  408. }
  409. // Support for planar_pixel_reference operator[]
  410. Element at_c_dynamic(std::size_t i) const
  411. {
  412. switch (i)
  413. {
  414. case 0: return v0_;
  415. case 1: return v1_;
  416. case 2: return v2_;
  417. case 3: return v3_;
  418. }
  419. return v4_;
  420. }
  421. private:
  422. Element v0_{};
  423. Element v1_{};
  424. Element v2_{};
  425. Element v3_{};
  426. Element v4_{};
  427. };
  428. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  429. #pragma warning(pop)
  430. #endif
  431. // The following way of casting adjacent channels (the contents of color_base) into an array appears to be unsafe
  432. // -- there is no guarantee that the compiler won't add any padding between adjacent channels.
  433. // Note, however, that GIL _must_ be compiled with compiler settings ensuring there is no padding in the color base structs.
  434. // This is because the color base structs must model the interleaved organization in memory. In other words, the client may
  435. // have existing RGB image in the form "RGBRGBRGB..." and we must be able to represent it with an array of RGB color bases (i.e. RGB pixels)
  436. // with no padding. We have tested with char/int/float/double channels on gcc and VC and have so far discovered no problem.
  437. // We have even tried using strange channels consisting of short + char (3 bytes). With the default 4-byte alignment on VC, the size
  438. // of this channel is padded to 4 bytes, so an RGB pixel of it will be 4x3=12 bytes. The code below will still work properly.
  439. // However, the client must nevertheless ensure that proper compiler settings are used for their compiler and their channel types.
  440. template <typename Element, typename Layout, int K>
  441. auto dynamic_at_c(homogeneous_color_base<Element,Layout,K>& cb, std::size_t i)
  442. -> typename element_reference_type<homogeneous_color_base<Element, Layout, K>>::type
  443. {
  444. BOOST_ASSERT(i < K);
  445. return (gil_reinterpret_cast<Element*>(&cb))[i];
  446. }
  447. template <typename Element, typename Layout, int K>
  448. auto dynamic_at_c(homogeneous_color_base<Element, Layout, K> const& cb, std::size_t i)
  449. -> typename element_const_reference_type
  450. <
  451. homogeneous_color_base<Element, Layout, K>
  452. >::type
  453. {
  454. BOOST_ASSERT(i < K);
  455. return (gil_reinterpret_cast_c<const Element*>(&cb))[i];
  456. }
  457. template <typename Element, typename Layout, int K>
  458. auto dynamic_at_c(homogeneous_color_base<Element&, Layout, K> const& cb, std::size_t i)
  459. -> typename element_reference_type
  460. <
  461. homogeneous_color_base<Element&, Layout, K>
  462. >::type
  463. {
  464. BOOST_ASSERT(i < K);
  465. return cb.at_c_dynamic(i);
  466. }
  467. template <typename Element, typename Layout, int K>
  468. auto dynamic_at_c(
  469. homogeneous_color_base<Element const&, Layout, K>const& cb, std::size_t i)
  470. -> typename element_const_reference_type
  471. <
  472. homogeneous_color_base<Element const&, Layout, K>
  473. >::type
  474. {
  475. BOOST_ASSERT(i < K);
  476. return cb.at_c_dynamic(i);
  477. }
  478. } // namespace detail
  479. template <typename Element, typename Layout, int K1, int K>
  480. struct kth_element_type<detail::homogeneous_color_base<Element, Layout, K1>, K>
  481. {
  482. using type = Element;
  483. };
  484. template <typename Element, typename Layout, int K1, int K>
  485. struct kth_element_reference_type<detail::homogeneous_color_base<Element, Layout, K1>, K>
  486. : std::add_lvalue_reference<Element>
  487. {};
  488. template <typename Element, typename Layout, int K1, int K>
  489. struct kth_element_const_reference_type
  490. <
  491. detail::homogeneous_color_base<Element, Layout, K1>,
  492. K
  493. >
  494. : std::add_lvalue_reference<typename std::add_const<Element>::type>
  495. {};
  496. /// \brief Provides mutable access to the K-th element, in physical order
  497. /// \ingroup ColorBaseModelHomogeneous
  498. template <int K, typename E, typename L, int N>
  499. inline
  500. auto at_c(detail::homogeneous_color_base<E, L, N>& p)
  501. -> typename std::add_lvalue_reference<E>::type
  502. {
  503. return p.at(std::integral_constant<int, K>());
  504. }
  505. /// \brief Provides constant access to the K-th element, in physical order
  506. /// \ingroup ColorBaseModelHomogeneous
  507. template <int K, typename E, typename L, int N>
  508. inline
  509. auto at_c(const detail::homogeneous_color_base<E, L, N>& p)
  510. -> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type
  511. {
  512. return p.at(std::integral_constant<int, K>());
  513. }
  514. namespace detail
  515. {
  516. struct swap_fn
  517. {
  518. template <typename T>
  519. void operator()(T& x, T& y) const
  520. {
  521. using std::swap;
  522. swap(x, y);
  523. }
  524. };
  525. } // namespace detail
  526. template <typename E, typename L, int N>
  527. inline
  528. void swap(
  529. detail::homogeneous_color_base<E, L, N>& x,
  530. detail::homogeneous_color_base<E, L, N>& y)
  531. {
  532. static_for_each(x, y, detail::swap_fn());
  533. }
  534. }} // namespace boost::gil
  535. #endif