reduce.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. /*
  2. Copyright 2005-2007 Adobe Systems Incorporated
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. See http://opensource.adobe.com/gil for most recent version including documentation.
  7. */
  8. /*************************************************************************************************/
  9. #ifndef GIL_REDUCE_HPP
  10. #define GIL_REDUCE_HPP
  11. #include <boost/mpl/insert_range.hpp>
  12. #include <boost/mpl/range_c.hpp>
  13. #include <boost/mpl/vector_c.hpp>
  14. #include <boost/mpl/back.hpp>
  15. #include <boost/mpl/vector.hpp>
  16. #include <boost/mpl/long.hpp>
  17. #include <boost/mpl/logical.hpp>
  18. #include <boost/mpl/transform.hpp>
  19. #include <boost/mpl/insert.hpp>
  20. #include <boost/mpl/transform.hpp>
  21. #include "../../metafunctions.hpp"
  22. #include "../../typedefs.hpp"
  23. #include "dynamic_at_c.hpp"
  24. ////////////////////////////////////////////////////////////////////////////////////////
  25. /// \file
  26. /// \brief Constructs for static-to-dynamic integer convesion
  27. /// \author Lubomir Bourdev and Hailin Jin \n
  28. /// Adobe Systems Incorporated
  29. /// \date 2005-2007 \n Last updated on May 4, 2006
  30. ///
  31. ////////////////////////////////////////////////////////////////////////////////////////
  32. #ifdef GIL_REDUCE_CODE_BLOAT
  33. // Max number of cases in the cross-expension of binary operation for it to be reduced as unary
  34. #define GIL_BINARY_REDUCE_LIMIT 226
  35. namespace boost { namespace mpl {
  36. ///////////////////////////////////////////////////////
  37. /// Mapping vector - represents the mapping of one type vector to another
  38. /// It is not a full-blown MPL Random Access Type sequence; just has at_c and size implemented
  39. ///
  40. /// SrcTypes, DstTypes: MPL Random Access Type Sequences
  41. ///
  42. /// Implements size and at_c to behave as if this is an MPL vector of integers
  43. ///////////////////////////////////////////////////////
  44. template <typename SrcTypes, typename DstTypes>
  45. struct mapping_vector {};
  46. template <typename SrcTypes, typename DstTypes, long K>
  47. struct at_c<mapping_vector<SrcTypes,DstTypes>, K> {
  48. static const std::size_t value=size<DstTypes>::value - order<DstTypes, typename at_c<SrcTypes,K>::type>::type::value +1;
  49. typedef size_t<value> type;
  50. };
  51. template <typename SrcTypes, typename DstTypes>
  52. struct size<mapping_vector<SrcTypes,DstTypes> > {
  53. typedef typename size<SrcTypes>::type type;
  54. static const std::size_t value=type::value;
  55. };
  56. ///////////////////////////////////////////////////////
  57. /// copy_to_vector - copies a sequence (mpl::set) to vector.
  58. ///
  59. /// Temporary solution because I couldn't get mpl::copy to do this.
  60. /// This is what I tried:
  61. /// mpl::copy<SET, mpl::back_inserter<mpl::vector<> > >::type;
  62. /// It works when SET is mpl::vector, but not when SET is mpl::set...
  63. ///////////////////////////////////////////////////////
  64. namespace detail {
  65. template <typename SFirst, std::size_t NLeft>
  66. struct copy_to_vector_impl {
  67. private:
  68. typedef typename deref<SFirst>::type T;
  69. typedef typename next<SFirst>::type next;
  70. typedef typename copy_to_vector_impl<next, NLeft-1>::type rest;
  71. public:
  72. typedef typename push_front<rest, T>::type type;
  73. };
  74. template <typename SFirst>
  75. struct copy_to_vector_impl<SFirst,1> {
  76. typedef vector<typename deref<SFirst>::type> type;
  77. };
  78. }
  79. template <typename Src>
  80. struct copy_to_vector {
  81. typedef typename detail::copy_to_vector_impl<typename begin<Src>::type, size<Src>::value>::type type;
  82. };
  83. template <>
  84. struct copy_to_vector<set<> > {
  85. typedef vector0<> type;
  86. };
  87. } } // boost::mpl
  88. namespace boost { namespace gil {
  89. ///////////////////////////////////////////////////////
  90. ///
  91. /// unary_reduce, binary_reduce - given an MPL Random Access Sequence,
  92. /// dynamically specified index to that container, the bits of an instance of the corresponding type and
  93. /// a generic operation, invokes the operation on the given type
  94. ///
  95. ///////////////////////////////////////////////////////
  96. ///////////////////////////////////////////////////////
  97. ///
  98. /// \brief Unary reduce.
  99. ///
  100. /// Given a set of types and an operation, reduces each type in the set (to reduced_t), then removes duplicates (to unique_t)
  101. /// To apply the operation, first constructs a lookup table that maps each element from Types to its place in unique_t and uses it to map
  102. /// the index to anther index (in map_index). Then invokes apply_operation_base on the unique types with the new index.
  103. ///
  104. ///////////////////////////////////////////////////////
  105. template <typename Types, typename Op>
  106. struct unary_reduce_impl {
  107. typedef typename mpl::transform<Types, detail::reduce<Op, mpl::_1> >::type reduced_t;
  108. typedef typename mpl::copy<reduced_t, mpl::inserter<mpl::set<>, mpl::insert<mpl::_1,mpl::_2> > >::type unique_t;
  109. static const bool is_single=mpl::size<unique_t>::value==1;
  110. };
  111. template <typename Types, typename Op, bool IsSingle=unary_reduce_impl<Types,Op>::is_single>
  112. struct unary_reduce : public unary_reduce_impl<Types,Op> {
  113. typedef typename unary_reduce_impl<Types,Op>::reduced_t reduced_t;
  114. typedef typename unary_reduce_impl<Types,Op>::unique_t unique_t;
  115. static unsigned short inline map_index(std::size_t index) {
  116. typedef typename mpl::mapping_vector<reduced_t, unique_t> indices_t;
  117. return gil::at_c<indices_t, unsigned short>(index);
  118. }
  119. template <typename Bits> GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
  120. return apply_operation_basec<unique_t>(bits,map_index(index),op);
  121. }
  122. template <typename Bits> GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
  123. return apply_operation_base<unique_t>(bits,map_index(index),op);
  124. }
  125. };
  126. template <typename Types, typename Op>
  127. struct unary_reduce<Types,Op,true> : public unary_reduce_impl<Types,Op> {
  128. typedef typename unary_reduce_impl<Types,Op>::unique_t unique_t;
  129. static unsigned short inline map_index(std::size_t index) { return 0; }
  130. template <typename Bits> GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
  131. return op(*gil_reinterpret_cast_c<const typename mpl::front<unique_t>::type*>(&bits));
  132. }
  133. template <typename Bits> GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
  134. return op(*gil_reinterpret_cast<typename mpl::front<unique_t>::type*>(&bits));
  135. }
  136. };
  137. ///////////////////////////////////////////////////////
  138. ///
  139. /// \brief Binary reduce.
  140. ///
  141. /// Given two sets of types, Types1 and Types2, first performs unary reduction on each. Then checks if the product of their sizes is above
  142. /// the GIL_BINARY_REDUCE_LIMIT limit. If so, the operation is too complex to be binary-reduced and uses a specialization of binary_reduce_impl
  143. /// to simply call the binary apply_operation_base (which performs two nested 1D apply operations)
  144. /// If the operation is not too complex, uses the other specialization of binary_reduce_impl to create a cross-product of the input types
  145. /// and performs unary reduction on the result (bin_reduced_t). To apply the binary operation, it simply invokes a unary apply_operation_base
  146. /// on the reduced cross-product types
  147. ///
  148. ///////////////////////////////////////////////////////
  149. namespace detail {
  150. struct pair_generator {
  151. template <typename Vec2> struct apply {
  152. typedef std::pair<const typename mpl::at_c<Vec2,0>::type*, const typename mpl::at_c<Vec2,1>::type*> type;
  153. };
  154. };
  155. // When the types are not too large, applies reduce on their cross product
  156. template <typename Unary1, typename Unary2, typename Op, bool IsComplex>
  157. struct binary_reduce_impl {
  158. //private:
  159. typedef typename mpl::copy_to_vector<typename Unary1::unique_t>::type vec1_types;
  160. typedef typename mpl::copy_to_vector<typename Unary2::unique_t>::type vec2_types;
  161. typedef mpl::cross_vector<mpl::vector2<vec1_types, vec2_types>, pair_generator> BIN_TYPES;
  162. typedef unary_reduce<BIN_TYPES,Op> bin_reduced_t;
  163. static unsigned short inline map_index(std::size_t index1, std::size_t index2) {
  164. unsigned short r1=Unary1::map_index(index1);
  165. unsigned short r2=Unary2::map_index(index2);
  166. return bin_reduced_t::map_index(r2*mpl::size<vec1_types>::value + r1);
  167. }
  168. public:
  169. typedef typename bin_reduced_t::unique_t unique_t;
  170. template <typename Bits1, typename Bits2>
  171. static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
  172. std::pair<const void*,const void*> pr(&bits1, &bits2);
  173. return apply_operation_basec<unique_t>(pr, map_index(index1,index2),op);
  174. }
  175. };
  176. // When the types are large performs a double-dispatch. Binary reduction is not done.
  177. template <typename Unary1, typename Unary2, typename Op>
  178. struct binary_reduce_impl<Unary1,Unary2,Op,true> {
  179. template <typename Bits1, typename Bits2>
  180. static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
  181. return apply_operation_base<Unary1::unique_t,Unary2::unique_t>(bits1, index1, bits2, index2, op);
  182. }
  183. };
  184. }
  185. template <typename Types1, typename Types2, typename Op>
  186. struct binary_reduce {
  187. //private:
  188. typedef unary_reduce<Types1,Op> unary1_t;
  189. typedef unary_reduce<Types2,Op> unary2_t;
  190. static const std::size_t CROSS_SIZE = mpl::size<typename unary1_t::unique_t>::value *
  191. mpl::size<typename unary2_t::unique_t>::value;
  192. typedef detail::binary_reduce_impl<unary1_t,unary2_t,Op, (CROSS_SIZE>GIL_BINARY_REDUCE_LIMIT)> impl;
  193. public:
  194. template <typename Bits1, typename Bits2>
  195. static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
  196. return impl::apply(bits1,index1,bits2,index2,op);
  197. }
  198. };
  199. template <typename Types, typename UnaryOp>
  200. GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(variant<Types>& arg, UnaryOp op) {
  201. return unary_reduce<Types,UnaryOp>::template apply(arg._bits, arg._index ,op);
  202. }
  203. template <typename Types, typename UnaryOp>
  204. GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(const variant<Types>& arg, UnaryOp op) {
  205. return unary_reduce<Types,UnaryOp>::template applyc(arg._bits, arg._index ,op);
  206. }
  207. template <typename Types1, typename Types2, typename BinaryOp>
  208. GIL_FORCEINLINE typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op) {
  209. return binary_reduce<Types1,Types2,BinaryOp>::template apply(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
  210. }
  211. #undef GIL_BINARY_REDUCE_LIMIT
  212. } } // namespace gil
  213. namespace boost { namespace mpl {
  214. ///////////////////////////////////////////////////////
  215. /// \brief Represents the virtual cross-product of the types generated from VecOfVecs.
  216. /// \ingroup CrossVector
  217. /// INPUT:
  218. /// VecOfVecs - a vector of vector types. For example [ [A1,A2,A3], [B1,B2], [C1,C2,C3,C4] ]
  219. /// Each element must be a non-empty mpl vector
  220. /// TypeGen - a metafunction that generates a type from a vector of types, each of which can be
  221. /// selected from the corresponding vector in VecOfVecs. For example, [A1, B2, C4]
  222. ///
  223. /// Represents the virtual cross-product of the types generated from VecOfVecs.
  224. /// For example, [ TypeGen[A1,B1,C1], TypeGen[A2,B1,C1], TypeGen[A3,B1,C1],
  225. /// TypeGen[A1,B2,C1], TypeGen[A2,B2,C1], TypeGen[A3,B2,C1],
  226. /// TypeGen[A1,B1,C2], TypeGen[A2,B1,C2], TypeGen[A3,B1,C2], ... ]
  227. ///
  228. /// Models an immutable MPL Random Access Sequence
  229. /// Traversal, random-access, etc, is defined, but mutable operations,
  230. /// such as push_back and pop_front are not supported
  231. ///////////////////////////////////////////////////////
  232. template <typename VecOfVecs, typename TypeGen>
  233. struct cross_vector {};
  234. /// \brief Iterator of cross_vector
  235. /// \ingroup CrossVectorIterator
  236. template <typename VecOfVecs, typename TypeGen, std::size_t K>
  237. struct cross_iterator {
  238. typedef mpl::random_access_iterator_tag category;
  239. };
  240. ///////////////////////////////////////////////////////
  241. /// Implementation of the iterator functions of cross vector
  242. ///////////////////////////////////////////////////////
  243. /// \brief Dereferences a cross-vector iterator
  244. /// \ingroup CrossVectorIterator
  245. /// Creates a vector of the sizes of each type vector in VecOfVecs, then uses it as a basis
  246. /// to represent the iterator's position K as a vector of indices. Extracts the corresponding type of
  247. /// each input vector and passes the element types to the type generation function, which returns the dereferenced type
  248. template <typename VecOfVecs, typename TypeGen, std::size_t K>
  249. struct deref<cross_iterator<VecOfVecs,TypeGen,K> > {
  250. private:
  251. typedef typename detail::select_subvector_c<VecOfVecs, K>::type DerefTypes;
  252. public:
  253. typedef typename TypeGen::template apply<DerefTypes>::type type;
  254. };
  255. /// \brief Increments a cross-vector iterator.
  256. /// \ingroup CrossVectorIterator
  257. template <typename VecOfVecs, typename TypeGen, std::size_t K>
  258. struct next<cross_iterator<VecOfVecs,TypeGen,K> > {
  259. typedef cross_iterator<VecOfVecs,TypeGen,K+1> type;
  260. };
  261. /// \brief Decrements a cross-vector iterator.
  262. /// \ingroup CrossVectorIterator
  263. template <typename VecOfVecs, typename TypeGen, std::size_t K>
  264. struct prior<cross_iterator<VecOfVecs,TypeGen,K> > {
  265. typedef cross_iterator<VecOfVecs,TypeGen,K-1> type;
  266. };
  267. /// \brief Advances a cross-vector iterator.
  268. /// \ingroup CrossVectorIterator
  269. template <typename VecOfVecs, typename TypeGen, std::size_t K, typename Distance>
  270. struct advance<cross_iterator<VecOfVecs,TypeGen,K>, Distance > {
  271. typedef cross_iterator<VecOfVecs,TypeGen,K+Distance::value> type;
  272. };
  273. /// \brief Computes the distance between two cross-vector iterator-s.
  274. /// \ingroup CrossVectorIterator
  275. // (shortened the names of the template arguments - otherwise doxygen cannot parse this...)
  276. template <typename VecOfVecs, typename TypeGen, std::size_t K1, std::size_t K2>
  277. struct distance<cross_iterator<VecOfVecs,TypeGen,K1>, cross_iterator<VecOfVecs,TypeGen,K2> > {
  278. typedef size_t<K2-K1> type;
  279. };
  280. ///////////////////////////////////////////////////////
  281. /// Implementation of cross vector
  282. ///////////////////////////////////////////////////////
  283. /// \brief Computes the size of a cross vector as the product of the sizes of all vectors in VecOfVecs
  284. /// \ingroup CrossVector
  285. template <typename VecOfVecs, typename TypeGen>
  286. struct size<cross_vector<VecOfVecs,TypeGen> > {
  287. typedef typename fold<VecOfVecs, size_t<1>, times<_1, size<_2> > >::type type;
  288. static const std::size_t value=type::value;
  289. };
  290. /// \brief Determines whether a cross vector is empty
  291. /// \ingroup CrossVector
  292. template <typename VecOfVecs, typename TypeGen>
  293. struct empty<cross_vector<VecOfVecs,TypeGen> > {
  294. typedef typename empty<VecOfVecs>::type type;
  295. };
  296. /// \brief Returns the K-th element of a cross vector
  297. /// \ingroup CrossVector
  298. template <typename VecOfVecs, typename TypeGen, typename K>
  299. struct at<cross_vector<VecOfVecs,TypeGen>, K> {
  300. private:
  301. typedef cross_iterator<VecOfVecs,TypeGen,K::value> KthIterator;
  302. public:
  303. typedef typename deref<KthIterator>::type type;
  304. };
  305. /// \brief Returns an iterator to the first element of a cross vector
  306. /// \ingroup CrossVector
  307. template <typename VecOfVecs, typename TypeGen>
  308. struct begin<cross_vector<VecOfVecs,TypeGen> > {
  309. typedef cross_iterator<VecOfVecs,TypeGen,0> type;
  310. };
  311. /// \brief Returns an iterator to the last element of a cross vector
  312. /// \ingroup CrossVector
  313. template <typename VecOfVecs, typename TypeGen>
  314. struct end<cross_vector<VecOfVecs,TypeGen> > {
  315. private:
  316. typedef cross_vector<VecOfVecs,TypeGen> this_t;
  317. public:
  318. typedef cross_iterator<VecOfVecs,TypeGen,size<this_t>::value> type;
  319. };
  320. /// \brief Returns the first element of a cross vector
  321. /// \ingroup CrossVector
  322. template <typename VecOfVecs, typename TypeGen>
  323. struct front<cross_vector<VecOfVecs,TypeGen> > {
  324. private:
  325. typedef cross_vector<VecOfVecs,TypeGen> this_t;
  326. public:
  327. typedef typename deref<typename begin<this_t>::type>::type type;
  328. };
  329. /// \brief Returns the last element of a cross vector
  330. /// \ingroup CrossVector
  331. template <typename VecOfVecs, typename TypeGen>
  332. struct back<cross_vector<VecOfVecs,TypeGen> > {
  333. private:
  334. typedef cross_vector<VecOfVecs,TypeGen> this_t;
  335. typedef typename size<this_t>::type size;
  336. typedef typename minus<size, size_t<1> >::type last_index;
  337. public:
  338. typedef typename at<this_t, last_index>::type type;
  339. };
  340. /// \brief Transforms the elements of a cross vector
  341. /// \ingroup CrossVector
  342. template <typename VecOfVecs, typename TypeGen, typename OPP>
  343. struct transform<cross_vector<VecOfVecs,TypeGen>, OPP > {
  344. typedef typename lambda<OPP>::type Op;
  345. struct adapter {
  346. template <typename Elements>
  347. struct apply {
  348. typedef typename TypeGen::template apply<Elements>::type orig_t;
  349. typedef typename Op::template apply<orig_t>::type type;
  350. };
  351. };
  352. typedef cross_vector<VecOfVecs, adapter > type;
  353. };
  354. } } // boost::mpl
  355. namespace boost { namespace gil {
  356. template <typename Types, typename T> struct type_to_index;
  357. template <typename V> struct view_is_basic;
  358. struct rgb_t;
  359. struct lab_t;
  360. struct hsb_t;
  361. struct cmyk_t;
  362. struct rgba_t;
  363. struct error_t;
  364. namespace detail {
  365. ////////////////////////////////////////////////////////
  366. ////
  367. //// Generic reduce operation
  368. ////
  369. ////////////////////////////////////////////////////////
  370. template <typename Op, typename T>
  371. struct reduce {
  372. typedef T type;
  373. };
  374. ////////////////////////////////////////////////////////
  375. ////
  376. //// Unary reduce_view operation. Splits into basic and non-basic views.
  377. //// Algorithm-specific reduce should specialize for basic views
  378. ////
  379. ////////////////////////////////////////////////////////
  380. template <typename Op, typename View, bool IsBasic>
  381. struct reduce_view_basic {
  382. typedef View type;
  383. };
  384. template <typename Op, typename Loc>
  385. struct reduce<Op, image_view<Loc> >
  386. : public reduce_view_basic<Op,image_view<Loc>,view_is_basic<image_view<Loc> >::value> {};
  387. ////////////////////////////////////////////////////////
  388. ////
  389. //// Unary reduce_image operation. Splits into basic and non-basic images.
  390. //// Algorithm-specific reduce should specialize for basic images
  391. ////
  392. ////////////////////////////////////////////////////////
  393. template <typename Op, typename Img, bool IsBasic>
  394. struct reduce_image_basic {
  395. typedef Img type;
  396. };
  397. template <typename Op, typename V, typename Alloc>
  398. struct reduce<Op, image<V,Alloc> > : public reduce_image_basic<Op,image<V,Alloc>,image_is_basic<image<V,Alloc> >::value > {};
  399. ////////////////////////////////////////////////////////
  400. ////
  401. //// Binary reduce_view operation. Splits into basic and non-basic views.
  402. //// Algorithm-specific reduce should specialize for basic views
  403. ////
  404. ////////////////////////////////////////////////////////
  405. template <typename Op, typename V1, typename V2, bool AreBasic>
  406. struct reduce_views_basic {
  407. typedef std::pair<const V1*, const V2*> type;
  408. };
  409. template <typename Op, typename L1, typename L2>
  410. struct reduce<Op, std::pair<const image_view<L1>*, const image_view<L2>*> >
  411. : public reduce_views_basic<Op,image_view<L1>,image_view<L2>,
  412. mpl::and_<view_is_basic<image_view<L1> >, view_is_basic<image_view<L2> > >::value >
  413. {};
  414. ////////////////////////////////////////////////////////
  415. ////
  416. //// Color space unary reduce operation. Reduce a color space to a base with the same number of channels
  417. ////
  418. ////////////////////////////////////////////////////////
  419. template <typename Cs>
  420. struct reduce_color_space {
  421. typedef Cs type;
  422. };
  423. template <> struct reduce_color_space<lab_t> { typedef rgb_t type; };
  424. template <> struct reduce_color_space<hsb_t> { typedef rgb_t type; };
  425. template <> struct reduce_color_space<cmyk_t> { typedef rgba_t type; };
  426. /*
  427. ////////////////////////////////////////////////////////
  428. ////
  429. //// Color space binary reduce operation. Given a source and destination color spaces,
  430. //// returns a reduced source and destination color spaces that have the same mapping of channels
  431. ////
  432. //// Precondition: The two color spaces must be compatible (i.e. must have the same set of channels)
  433. ////////////////////////////////////////////////////////
  434. template <typename Vec, int Basis, int VecSize>
  435. struct type_vec_to_integer_impl {
  436. typedef typename mpl::back<Vec>::type last;
  437. typedef typename mpl::pop_back<Vec>::type rest;
  438. static const int value = type_vec_to_integer_impl<rest, Basis, VecSize-1>::value * Basis + last::value;
  439. };
  440. template <typename Vec, int Basis>
  441. struct type_vec_to_integer_impl<Vec,Basis,0> {
  442. static const int value=0;
  443. };
  444. template <typename Vec, int Basis=10>
  445. struct type_vec_to_integer {
  446. static const int value = type_vec_to_integer_impl<Vec,Basis, mpl::size<Vec>::value>::value;
  447. };
  448. // Given two color spaces and the mapping of the channels between them, returns the reduced pair of color spaces
  449. // The default version performs no reduction
  450. template <typename SrcColorSpace, typename DstColorSpace, int Mapping>
  451. struct reduce_color_spaces_impl {
  452. typedef SrcColorSpace first_t;
  453. typedef DstColorSpace second_t;
  454. };
  455. // 012: RGB-RGB, bgr-bgr, lab-lab, hsb-hsb
  456. template <typename SrcColorSpace, typename DstColorSpace>
  457. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,12> {
  458. typedef rgb_t first_t;
  459. typedef rgb_t second_t;
  460. };
  461. // 210: RGB-bgr, bgr-RGB
  462. template <typename SrcColorSpace, typename DstColorSpace>
  463. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,210> {
  464. typedef rgb_t first_t;
  465. typedef bgr_t second_t;
  466. };
  467. // 0123: RGBA-RGBA, bgra-bgra, argb-argb, abgr-abgr cmyk-cmyk
  468. template <typename SrcColorSpace, typename DstColorSpace>
  469. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,123> {
  470. typedef rgba_t first_t;
  471. typedef rgba_t second_t;
  472. };
  473. // 3210: RGBA-abgr, bgra-argb, argb-bgra, abgr-RGBA
  474. template <typename SrcColorSpace, typename DstColorSpace>
  475. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3210> {
  476. typedef rgba_t first_t;
  477. typedef abgr_t second_t;
  478. };
  479. // 1230: RGBA-argb, bgra-abgr
  480. template <typename SrcColorSpace, typename DstColorSpace>
  481. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,1230> {
  482. typedef rgba_t first_t;
  483. typedef argb_t second_t;
  484. };
  485. // 2103: RGBA-bgra, bgra-RGBA (uses subclass to ensure that base color space is not reduced to derived)
  486. template <typename SrcColorSpace, typename DstColorSpace>
  487. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,2103> {
  488. typedef rgba_t first_t;
  489. typedef bgra_t second_t;
  490. };
  491. // 3012: argb-RGBA, abgr-bgra
  492. template <typename SrcColorSpace, typename DstColorSpace>
  493. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3012> {
  494. typedef argb_t first_t;
  495. typedef rgba_t second_t;
  496. };
  497. // 0321: argb-abgr, abgr-argb
  498. template <typename SrcColorSpace, typename DstColorSpace>
  499. struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,321> {
  500. typedef argb_t first_t;
  501. typedef abgr_t second_t;
  502. };
  503. template <typename SrcColorSpace, typename DstColorSpace>
  504. struct reduce_color_spaces {
  505. typedef typename channel_order<SrcColorSpace>::type src_order_t;
  506. typedef typename channel_order<DstColorSpace>::type dst_order_t;
  507. typedef typename mpl::transform<src_order_t, type_to_index<dst_order_t,mpl::_1> >::type mapping;
  508. static const int mapping_val = type_vec_to_integer<mapping>::value;
  509. typedef typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::first_t _first_t;
  510. typedef typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::second_t _second_t;
  511. typedef typename mpl::and_<color_space_is_base<DstColorSpace>, mpl::not_< color_space_is_base<_second_t> > > swap_t;
  512. public:
  513. typedef typename mpl::if_<swap_t, _second_t, _first_t>::type first_t;
  514. typedef typename mpl::if_<swap_t, _first_t, _second_t>::type second_t;
  515. };
  516. */
  517. // TODO: Use the old code for reduce_color_spaces above to do color layout reduction
  518. template <typename SrcLayout, typename DstLayout>
  519. struct reduce_color_layouts {
  520. typedef SrcLayout first_t;
  521. typedef DstLayout second_t;
  522. };
  523. ////////////////////////////////////////////////////////
  524. ////
  525. //// Reduce for copy_pixels
  526. ////
  527. ////////////////////////////////////////////////////////
  528. struct copy_pixels_fn;
  529. /*
  530. // 1D reduce for copy_pixels reduces the channel to mutable and the color space to its base with same dimensions
  531. template <typename View>
  532. struct reduce_view_basic<copy_pixels_fn,View,true> {
  533. private:
  534. typedef typename reduce_color_space<typename View::color_space_t>::type Cs; // reduce the color space
  535. typedef layout<Cs, typename View::channel_mapping_t> layout_t;
  536. public:
  537. typedef typename derived_view_type<View, use_default, layout_t, use_default, use_default, mpl::true_>::type type;
  538. };
  539. */
  540. // Incompatible views cannot be used in copy_pixels - will throw std::bad_cast
  541. template <typename V1, typename V2, bool Compatible>
  542. struct reduce_copy_pixop_compat {
  543. typedef error_t type;
  544. };
  545. // For compatible basic views, reduce their color spaces based on their channel mapping.
  546. // Make the source immutable and the destination mutable (they should already be that way)
  547. template <typename V1, typename V2>
  548. struct reduce_copy_pixop_compat<V1,V2,true> {
  549. typedef layout<typename V1::color_space_t, typename V1::channel_mapping_t> layout1;
  550. typedef layout<typename V2::color_space_t, typename V2::channel_mapping_t> layout2;
  551. typedef typename reduce_color_layouts<layout1,layout2>::first_t L1;
  552. typedef typename reduce_color_layouts<layout1,layout2>::second_t L2;
  553. typedef typename derived_view_type<V1, use_default, L1, use_default, use_default, use_default, mpl::false_>::type DV1;
  554. typedef typename derived_view_type<V2, use_default, L2, use_default, use_default, use_default, mpl::true_ >::type DV2;
  555. typedef std::pair<const DV1*, const DV2*> type;
  556. };
  557. // The general 2D version branches into compatible and incompatible views
  558. template <typename V1, typename V2>
  559. struct reduce_views_basic<copy_pixels_fn, V1, V2, true>
  560. : public reduce_copy_pixop_compat<V1, V2, mpl::and_<views_are_compatible<V1,V2>, view_is_mutable<V2> >::value > {
  561. };
  562. ////////////////////////////////////////////////////////
  563. ////
  564. //// Reduce for variant destructor (basic views have no destructor)
  565. ////
  566. ////////////////////////////////////////////////////////
  567. struct destructor_op;
  568. template <typename View> struct reduce_view_basic<destructor_op,View,true> { typedef gray8_view_t type; };
  569. ////////////////////////////////////////////////////////
  570. ////
  571. //// Reduce for get_dimensions (basic views and images have the same structure and the dimensions are contained at the beginning)
  572. ////
  573. ////////////////////////////////////////////////////////
  574. struct any_type_get_dimensions;
  575. template <typename View> struct reduce_view_basic<any_type_get_dimensions,View,true> { typedef gray8_view_t type; };
  576. template <typename Img> struct reduce_image_basic<any_type_get_dimensions,Img,true> { typedef gray8_image_t type; };
  577. ////////////////////////////////////////////////////////
  578. ////
  579. //// Reduce for get_num_channels (only color space matters)
  580. ////
  581. ////////////////////////////////////////////////////////
  582. struct any_type_get_num_channels;
  583. template <typename View> struct reduce_view_basic<any_type_get_num_channels,View,true> {
  584. typedef typename View::color_space_t::base Cs;
  585. typedef typename view_type<bits8,typename reduce_color_space<Cs>::type>::type type;
  586. };
  587. template <typename Img> struct reduce_image_basic<any_type_get_num_channels,Img,true> {
  588. typedef typename Img::color_space_t::base Cs;
  589. typedef typename image_type<bits8,typename reduce_color_space<Cs>::type>::type type;
  590. };
  591. ////////////////////////////////////////////////////////
  592. ////
  593. //// Reduce for resample_pixels (same as copy_pixels)
  594. ////
  595. ////////////////////////////////////////////////////////
  596. template <typename Sampler, typename MapFn> struct resample_pixels_fn;
  597. template <typename S, typename M, typename V, bool IsBasic>
  598. struct reduce_view_basic<resample_pixels_fn<S,M>, V, IsBasic> : public reduce_view_basic<copy_pixels_fn, V, IsBasic> {};
  599. template <typename S, typename M, typename V1, typename V2, bool IsBasic>
  600. struct reduce_views_basic<resample_pixels_fn<S,M>, V1, V2, IsBasic> : public reduce_views_basic<copy_pixels_fn, V1, V2, IsBasic> {};
  601. ////////////////////////////////////////////////////////
  602. ////
  603. //// Reduce for copy_and_convert_pixels
  604. //// (the only reduction could be made when views are compatible and have the same mapping, planarity and stepness)
  605. ////
  606. ////////////////////////////////////////////////////////
  607. template <typename CC> class copy_and_convert_pixels_fn;
  608. // the only thing for 1D reduce is making them all mutable...
  609. template <typename CC, typename View, bool IsBasic>
  610. struct reduce_view_basic<copy_and_convert_pixels_fn<CC>, View, IsBasic>
  611. : public derived_view_type<View, use_default, use_default, use_default, use_default, mpl::true_> {
  612. };
  613. // For 2D reduce, if they have the same channels and color spaces (i.e. the same pixels) then copy_and_convert is just copy.
  614. // In this case, reduce their common color space. In general make the first immutable and the second mutable
  615. template <typename CC, typename V1, typename V2, bool AreBasic>
  616. struct reduce_views_basic<copy_and_convert_pixels_fn<CC>, V1, V2, AreBasic> {
  617. typedef is_same<typename V1::pixel_t, typename V2::pixel_t> Same;
  618. typedef reduce_color_space<typename V1::color_space_t::base> CsR;
  619. typedef typename mpl::if_<Same, typename CsR::type, typename V1::color_space_t>::type Cs1;
  620. typedef typename mpl::if_<Same, typename CsR::type, typename V2::color_space_t>::type Cs2;
  621. typedef typename derived_view_type<V1, use_default, layout<Cs1, typename V1::channel_mapping_t>, use_default, use_default, mpl::false_>::type DV1;
  622. typedef typename derived_view_type<V2, use_default, layout<Cs2, typename V2::channel_mapping_t>, use_default, use_default, mpl::true_ >::type DV2;
  623. typedef std::pair<const DV1*, const DV2*> type;
  624. };
  625. //integral_image_generator
  626. //resize_clobber_image_fnobj
  627. //image_default_construct_fnobj
  628. //fill_converted_pixels_fn
  629. //bind(gil::detail::copy_pixels_fn(), _1, dst)
  630. //bind(gil::detail::copy_pixels_fn(), src,_1)
  631. //bind(detail::copy_and_convert_pixels_fn(), _1, dst)
  632. //bind(detail::copy_and_convert_pixels_fn(), src, _1)
  633. //gil::detail::fill_pixels_fn<Value>(val)
  634. //detail::copy_construct_in_place_fn<base_t>
  635. //detail::equal_to_fn<typename variant<Types>::base_t>
  636. //detail::any_image_get_view<typename any_image<Types>::view_t>
  637. //detail::any_image_get_const_view<typename any_image<Types>::view_t>
  638. //detail::flipped_up_down_view_fn<any_image_view<ViewTypes> >
  639. //detail::flipped_left_right_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
  640. //detail::tranposed_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
  641. //detail::rotated90cw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
  642. //detail::rotated90ccw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
  643. //detail::rotated180_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
  644. //detail::subimage_view_fn<any_image_view<ViewTypes> >
  645. //detail::subsampled_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
  646. //detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes> >
  647. //detail::color_converted_view_fn<DstP,typename color_convert_view_type<any_image_view<ViewTypes>, DstP>::type >
  648. }
  649. } } // namespace boost::gil
  650. #endif // GIL_REDUCE_CODE_BLOAT
  651. #endif