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