Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page

# metafunctions.hpp

Go to the documentation of this file.

    00001 /*
    00002     Copyright 2005-2007 Adobe Systems Incorporated
    00003
    00004     Use, modification and distribution are subject to the Boost Software License,
    00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    00006     http://www.boost.org/LICENSE_1_0.txt).
    00007
    00008     See http://opensource.adobe.com/gil for most recent version including documentation.
    00009 */
    00010
    00011 /*************************************************************************************************/
    00012
    00013 #ifndef GIL_METAFUNCTIONS_HPP
    00014 #define GIL_METAFUNCTIONS_HPP
    00015
    00025
    00026 #include <iterator>
    00027 #include <boost/mpl/accumulate.hpp>
    00028 #include <boost/mpl/back.hpp>
    00029 #include <boost/mpl/bool.hpp>
    00030 #include <boost/mpl/if.hpp>
    00031 #include <boost/mpl/pop_back.hpp>
    00032 #include <boost/mpl/push_back.hpp>
    00033 #include <boost/mpl/transform.hpp>
    00034 #include <boost/mpl/vector.hpp>
    00035 #include <boost/type_traits.hpp>
    00036 #include "gil_config.hpp"
    00037 #include "gil_concept.hpp"
    00038 #include "channel.hpp"
    00039
    00040 namespace boost { namespace gil {
    00041
    00042 // forward declarations
    00043 template <typename T, typename L> struct pixel;
    00044 template <typename BitField,typename ChannelRefVec,typename Layout> struct packed_pixel;
    00045 template <typename T, typename C> struct planar_pixel_reference;
    00046 template <typename IC, typename C> struct planar_pixel_iterator;
    00047 template <typename I> class memory_based_step_iterator;
    00048 template <typename I> class memory_based_2d_locator;
    00049 template <typename L> class image_view;
    00050 template <typename Pixel, bool IsPlanar, typename Alloc> class image;
    00051 template <typename T> struct channel_type;
    00052 template <typename T> struct color_space_type;
    00053 template <typename T> struct channel_mapping_type;
    00054 template <typename It> struct is_iterator_adaptor;
    00055 template <typename It> struct iterator_adaptor_get_base;
    00056 template <typename BitField, typename ChannelBitSizes, typename Layout, bool IsMutable> struct bit_aligned_pixel_reference;
    00057
    00064
    00065
    00072
    00076 template <typename PixelRef>        struct pixel_reference_is_basic                     : public mpl::false_ {};
    00077 template <typename T,  typename L>  struct pixel_reference_is_basic<      pixel<T,L>&>  : public mpl::true_ {};
    00078 template <typename T,  typename L>  struct pixel_reference_is_basic<const pixel<T,L>&>  : public mpl::true_ {};
    00079 template <typename TR, typename Cs> struct pixel_reference_is_basic<planar_pixel_reference<TR,Cs> > : public mpl::true_ {};
    00080 template <typename TR, typename Cs> struct pixel_reference_is_basic<const planar_pixel_reference<TR,Cs> > : public mpl::true_ {};
    00081
    00082
    00086 template <typename Iterator>
    00087 struct iterator_is_basic : public mpl::false_ {};
    00088 template <typename T, typename L>  // mutable   interleaved
    00089 struct iterator_is_basic<      pixel<T,L>*      > : public mpl::true_ {};
    00090 template <typename T, typename L>  // immutable interleaved
    00091 struct iterator_is_basic<const pixel<T,L>*      > : public mpl::true_ {};
    00092 template <typename T, typename Cs>  // mutable   planar
    00093 struct iterator_is_basic<planar_pixel_iterator<      T*,Cs> > : public mpl::true_ {};
    00094 template <typename T, typename Cs>    // immutable planar
    00095 struct iterator_is_basic<planar_pixel_iterator<const T*,Cs> > : public mpl::true_ {};
    00096 template <typename T, typename L>  // mutable   interleaved step
    00097 struct iterator_is_basic<memory_based_step_iterator<      pixel<T,L>*> > : public mpl::true_ {};
    00098 template <typename T, typename L>  // immutable interleaved step
    00099 struct iterator_is_basic<memory_based_step_iterator<const pixel<T,L>*> > : public mpl::true_ {};
    00100 template <typename T, typename Cs>  // mutable   planar step
    00101 struct iterator_is_basic<memory_based_step_iterator<planar_pixel_iterator<      T*,Cs> > > : public mpl::true_ {};
    00102 template <typename T, typename Cs>    // immutable planar step
    00103 struct iterator_is_basic<memory_based_step_iterator<planar_pixel_iterator<const T*,Cs> > > : public mpl::true_ {};
    00104
    00105
    00108 template <typename Loc> struct locator_is_basic : public mpl::false_ {};
    00109 template <typename Iterator> struct locator_is_basic<memory_based_2d_locator<memory_based_step_iterator<Iterator> > > : public iterator_is_basic<Iterator> {};
    00110
    00113 template <typename View> struct view_is_basic : public mpl::false_ {};
    00114 template <typename Loc> struct view_is_basic<image_view<Loc> > : public locator_is_basic<Loc> {};
    00115
    00118 template <typename Img> struct image_is_basic : public mpl::false_ {};
    00119 template <typename Pixel, bool IsPlanar, typename Alloc> struct image_is_basic<image<Pixel,IsPlanar,Alloc> > : public mpl::true_ {};
    00120
    00121
    00125
    00126 template <typename I> struct iterator_is_step;
    00127 namespace detail {
    00128     template <typename It, bool IsBase, bool EqualsStepType> struct iterator_is_step_impl;
    00129     // iterator that has the same type as its dynamic_x_step_type must be a step iterator
    00130     template <typename It, bool IsBase> struct iterator_is_step_impl<It,IsBase,true> : public mpl::true_{};
    00131
    00132     // base iterator can never be a step iterator
    00133     template <typename It> struct iterator_is_step_impl<It,true,false> : public mpl::false_{};
    00134
    00135     // for an iterator adaptor, see if its base is step
    00136     template <typename It> struct iterator_is_step_impl<It,false,false>
    00137         : public iterator_is_step<typename iterator_adaptor_get_base<It>::type>{};
    00138 }
    00139
    00142 template <typename I> struct iterator_is_step
    00143     : public detail::iterator_is_step_impl<I,
    00144         !is_iterator_adaptor<I>::type::value,
    00145         is_same<I,typename dynamic_x_step_type<I>::type>::value >{};
    00146
    00149 template <typename L> struct locator_is_step_in_x : public iterator_is_step<typename L::x_iterator> {};
    00150
    00153 template <typename L> struct locator_is_step_in_y : public iterator_is_step<typename L::y_iterator> {};
    00154
    00157 template <typename V> struct view_is_step_in_x : public locator_is_step_in_x<typename V::xy_locator> {};
    00158
    00161 template <typename V> struct view_is_step_in_y : public locator_is_step_in_y<typename V::xy_locator> {};
    00162
    00165 template <typename PixelReference>
    00166 struct pixel_reference_is_proxy
    00167     : public mpl::not_<is_same<typename remove_const_and_reference<PixelReference>::type,
    00168                                typename remove_const_and_reference<PixelReference>::type::value_type> > {};
    00169
    00172 template <typename Pixel>
    00173 struct pixel_is_reference : public mpl::or_<is_reference<Pixel>, pixel_reference_is_proxy<Pixel> > {};
    00174
    00178
    00183 template <typename R> struct pixel_reference_is_mutable : public mpl::bool_<remove_reference<R>::type::is_mutable> {};
    00184 template <typename R> struct pixel_reference_is_mutable<const R&>
    00185     : public mpl::and_<pixel_reference_is_proxy<R>, pixel_reference_is_mutable<R> > {};
    00186
    00189 template <typename L> struct locator_is_mutable : public iterator_is_mutable<typename L::x_iterator> {};
    00192 template <typename V> struct view_is_mutable : public iterator_is_mutable<typename V::x_iterator> {};
    00193
    00194
    00201
    00205
    00209
    00213
    00216 template <typename T, typename L, bool IsPlanar=false, bool IsMutable=true> struct pixel_reference_type{};
    00217 template <typename T, typename L> struct pixel_reference_type<T,L,false,true > { typedef pixel<T,L>& type; };
    00218 template <typename T, typename L> struct pixel_reference_type<T,L,false,false> { typedef const pixel<T,L>& type; };
    00219 template <typename T, typename L> struct pixel_reference_type<T,L,true,true> { typedef const planar_pixel_reference<typename channel_traits<T>::reference,typename color_space_type<L>::type> type; };       // TODO: Assert M=identity
    00220 template <typename T, typename L> struct pixel_reference_type<T,L,true,false> { typedef const planar_pixel_reference<typename channel_traits<T>::const_reference,typename color_space_type<L>::type> type; };// TODO: Assert M=identity
    00221
    00224 template <typename Pixel, bool IsPlanar=false, bool IsStep=false, bool IsMutable=true> struct iterator_type_from_pixel{};
    00225 template <typename Pixel> struct iterator_type_from_pixel<Pixel,false,false,true > { typedef Pixel* type; };
    00226 template <typename Pixel> struct iterator_type_from_pixel<Pixel,false,false,false> { typedef const Pixel* type; };
    00227 template <typename Pixel> struct iterator_type_from_pixel<Pixel,true,false,true> {
    00228     typedef planar_pixel_iterator<typename channel_traits<typename channel_type<Pixel>::type>::pointer,typename color_space_type<Pixel>::type> type;
    00229 };
    00230 template <typename Pixel> struct iterator_type_from_pixel<Pixel,true,false,false> {
    00231     typedef planar_pixel_iterator<typename channel_traits<typename channel_type<Pixel>::type>::const_pointer,typename color_space_type<Pixel>::type> type;
    00232 };
    00233 template <typename Pixel, bool IsPlanar, bool IsMutable> struct iterator_type_from_pixel<Pixel,IsPlanar,true,IsMutable> {
    00234     typedef memory_based_step_iterator<typename iterator_type_from_pixel<Pixel,IsPlanar,false,IsMutable>::type> type;
    00235 };
    00236
    00239 template <typename T, typename L, bool IsPlanar=false, bool IsStep=false, bool IsMutable=true> struct iterator_type{};
    00240 template <typename T, typename L> struct iterator_type<T,L,false,false,true > { typedef pixel<T,L>* type; };
    00241 template <typename T, typename L> struct iterator_type<T,L,false,false,false> { typedef const pixel<T,L>* type; };
    00242 template <typename T, typename L> struct iterator_type<T,L,true,false,true> { typedef planar_pixel_iterator<T*,typename L::color_space_t> type; };               // TODO: Assert M=identity
    00243 template <typename T, typename L> struct iterator_type<T,L,true,false,false> { typedef planar_pixel_iterator<const T*,typename L::color_space_t> type; };        // TODO: Assert M=identity
    00244 template <typename T, typename L, bool IsPlanar, bool IsMutable> struct iterator_type<T,L,IsPlanar,true,IsMutable> {
    00245     typedef memory_based_step_iterator<typename iterator_type<T,L,IsPlanar,false,IsMutable>::type> type;
    00246 };
    00247
    00250 template <typename XIterator>
    00251 struct type_from_x_iterator {
    00252     typedef memory_based_step_iterator<XIterator>    step_iterator_t;
    00253     typedef memory_based_2d_locator<step_iterator_t> xy_locator_t;
    00254     typedef image_view<xy_locator_t>                     view_t;
    00255 };
    00256
    00257 namespace detail {
    00258     template <typename BitField, typename FirstBit, typename NumBits>
    00259     struct packed_channel_reference_type {
    00260         typedef const packed_channel_reference<BitField,FirstBit::value,NumBits::value,true> type;
    00261     };
    00262
    00263     template <typename BitField, typename ChannelBitSizesVector>
    00264     class packed_channel_references_vector_type {
    00265         // If ChannelBitSizesVector is mpl::vector<int,7,7,2>
    00266         // Then first_bits_vector will be mpl::vector<int,0,7,14,16>
    00267         typedef typename mpl::accumulate<ChannelBitSizesVector, mpl::vector1<mpl::int_<0> >,
    00268             mpl::push_back<mpl::_1, mpl::plus<mpl::back<mpl::_1>, mpl::_2> > >::type first_bits_vector;
    00269     public:
    00270         typedef typename mpl::transform<typename mpl::pop_back<first_bits_vector>::type, ChannelBitSizesVector,
    00271                packed_channel_reference_type<BitField, mpl::_1,mpl::_2> >::type type;
    00272     };
    00273
    00274 }
    00275
    00284 template <typename BitField, typename ChannelBitSizeVector, typename Layout>
    00285 struct packed_pixel_type {
    00286     typedef packed_pixel<BitField, typename detail::packed_channel_references_vector_type<BitField,ChannelBitSizeVector>::type, Layout> type;
    00287 };
    00288
    00297
    00300 template <typename BitField, typename ChannelBitSizeVector, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00301 struct packed_image_type {
    00302     typedef image<typename packed_pixel_type<BitField,ChannelBitSizeVector,Layout>::type,false,Alloc> type;
    00303 };
    00304
    00307 template <typename BitField, unsigned Size1, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00308 struct packed_image1_type : public packed_image_type<BitField, mpl::vector1_c<unsigned, Size1>, Layout, Alloc> {};
    00309
    00312 template <typename BitField, unsigned Size1, unsigned Size2, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00313 struct packed_image2_type : public packed_image_type<BitField, mpl::vector2_c<unsigned, Size1, Size2>, Layout, Alloc> {};
    00314
    00317 template <typename BitField, unsigned Size1, unsigned Size2, unsigned Size3, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00318 struct packed_image3_type : public packed_image_type<BitField, mpl::vector3_c<unsigned, Size1, Size2, Size3>, Layout, Alloc> {};
    00319
    00322 template <typename BitField, unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00323 struct packed_image4_type : public packed_image_type<BitField, mpl::vector4_c<unsigned, Size1, Size2, Size3, Size4>, Layout, Alloc> {};
    00324
    00327 template <typename BitField, unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4, unsigned Size5, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00328 struct packed_image5_type : public packed_image_type<BitField, mpl::vector5_c<unsigned, Size1, Size2, Size3, Size4, Size5>, Layout, Alloc> {};
    00329
    00330
    00336
    00337 template <typename ChannelBitSizeVector, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00338 struct bit_aligned_image_type {
    00339 private:
    00340     BOOST_STATIC_CONSTANT(int, bit_size = (mpl::accumulate<ChannelBitSizeVector, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type::value));
    00341     typedef typename detail::min_fast_uint<bit_size+7>::type                        bitfield_t;
    00342     typedef const bit_aligned_pixel_reference<bitfield_t, ChannelBitSizeVector, Layout, true> bit_alignedref_t;
    00343 public:
    00344     typedef image<bit_alignedref_t,false,Alloc> type;
    00345 };
    00346
    00349 template <unsigned Size1, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00350 struct bit_aligned_image1_type : public bit_aligned_image_type<mpl::vector1_c<unsigned, Size1>, Layout, Alloc> {};
    00351
    00354 template <unsigned Size1, unsigned Size2, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00355 struct bit_aligned_image2_type : public bit_aligned_image_type<mpl::vector2_c<unsigned, Size1, Size2>, Layout, Alloc> {};
    00356
    00359 template <unsigned Size1, unsigned Size2, unsigned Size3, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00360 struct bit_aligned_image3_type : public bit_aligned_image_type<mpl::vector3_c<unsigned, Size1, Size2, Size3>, Layout, Alloc> {};
    00361
    00364 template <unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00365 struct bit_aligned_image4_type : public bit_aligned_image_type<mpl::vector4_c<unsigned, Size1, Size2, Size3, Size4>, Layout, Alloc> {};
    00366
    00369 template <unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4, unsigned Size5, typename Layout, typename Alloc=std::allocator<unsigned char> >
    00370 struct bit_aligned_image5_type : public bit_aligned_image_type<mpl::vector5_c<unsigned, Size1, Size2, Size3, Size4, Size5>, Layout, Alloc> {};
    00371
    00372
    00373
    00376 template <typename Channel, typename Layout>
    00377 struct pixel_value_type {
    00378     typedef pixel<Channel,Layout> type;     // by default use gil::pixel. Specializations are provided for
    00379 };
    00380
    00381 // Specializations for packed channels
    00382 template <typename BitField, int NumBits, bool IsMutable, typename Layout>
    00383 struct pixel_value_type<      packed_dynamic_channel_reference<BitField,NumBits,IsMutable>,Layout> :
    00384     public packed_pixel_type<BitField, mpl::vector1_c<unsigned,NumBits>, Layout> {};
    00385 template <typename BitField, int NumBits, bool IsMutable, typename Layout>
    00386 struct pixel_value_type<const packed_dynamic_channel_reference<BitField,NumBits,IsMutable>,Layout> :
    00387     public packed_pixel_type<BitField, mpl::vector1_c<unsigned,NumBits>, Layout> {};
    00388
    00389 template <typename BitField, int FirstBit, int NumBits, bool IsMutable, typename Layout>
    00390 struct pixel_value_type<      packed_channel_reference<BitField,FirstBit,NumBits,IsMutable>,Layout> :
    00391     public packed_pixel_type<BitField, mpl::vector1_c<unsigned,NumBits>, Layout> {};
    00392 template <typename BitField, int FirstBit, int NumBits, bool IsMutable, typename Layout>
    00393 struct pixel_value_type<const packed_channel_reference<BitField,FirstBit,NumBits,IsMutable>,Layout> :
    00394     public packed_pixel_type<BitField, mpl::vector1_c<unsigned,NumBits>, Layout> {};
    00395
    00396 template <int NumBits, typename Layout>
    00397 struct pixel_value_type<packed_channel_value<NumBits>,Layout> :
    00398     public packed_pixel_type<typename detail::min_fast_uint<NumBits>::type, mpl::vector1_c<unsigned,NumBits>, Layout> {};
    00399
    00400
    00403 template <typename T, typename L, bool IsPlanar=false, bool IsStepX=false, bool IsMutable=true>
    00404 struct locator_type {
    00405     typedef typename type_from_x_iterator<typename iterator_type<T,L,IsPlanar,IsStepX,IsMutable>::type>::xy_locator_type type;
    00406 };
    00407
    00410 template <typename T, typename L, bool IsPlanar=false, bool IsStepX=false, bool IsMutable=true>
    00411 struct view_type {
    00412     typedef typename type_from_x_iterator<typename iterator_type<T,L,IsPlanar,IsStepX,IsMutable>::type>::view_t type;
    00413 };
    00414
    00417 template <typename T, typename L, bool IsPlanar=false, typename Alloc=std::allocator<unsigned char> >
    00418 struct image_type {
    00419     typedef image<pixel<T,L>, IsPlanar, Alloc> type;
    00420 };
    00421
    00424 template <typename Pixel, bool IsPlanar=false, bool IsStepX=false, bool IsMutable=true>
    00425 struct view_type_from_pixel {
    00426     typedef typename type_from_x_iterator<typename iterator_type_from_pixel<Pixel,IsPlanar,IsStepX,IsMutable>::type>::view_t type;
    00427 };
    00428
    00429
    00433 template <typename Ref, typename T=use_default, typename L=use_default, typename IsPlanar=use_default, typename IsMutable=use_default>
    00434 class derived_pixel_reference_type {
    00435     typedef typename remove_reference<Ref>::type pixel_t;
    00436     typedef typename  mpl::if_<is_same<T, use_default>, typename channel_type<pixel_t>::type,     T >::type channel_t;
    00437     typedef typename  mpl::if_<is_same<L, use_default>,
    00438         layout<typename color_space_type<pixel_t>::type, typename channel_mapping_type<pixel_t>::type>, L>::type           layout_t;
    00439     static const bool mut   =mpl::if_<is_same<IsMutable,use_default>, pixel_reference_is_mutable<Ref>, IsMutable>::type::value;
    00440     static const bool planar=mpl::if_<is_same<IsPlanar,use_default>,  is_planar<pixel_t>,  IsPlanar>::type::value;
    00441 public:
    00442     typedef typename pixel_reference_type<channel_t, layout_t, planar, mut>::type type;
    00443 };
    00444
    00448 template <typename Iterator, typename T=use_default, typename L=use_default, typename IsPlanar=use_default, typename IsStep=use_default, typename IsMutable=use_default>
    00449 class derived_iterator_type {
    00450     typedef typename  mpl::if_<is_same<T ,use_default>, typename channel_type<Iterator>::type,     T >::type channel_t;
    00451     typedef typename  mpl::if_<is_same<L,use_default>,
    00452         layout<typename color_space_type<Iterator>::type, typename channel_mapping_type<Iterator>::type>, L>::type layout_t;
    00453
    00454     static const bool mut   =mpl::if_<is_same<IsMutable,use_default>, iterator_is_mutable<Iterator>, IsMutable>::type::value;
    00455     static const bool planar=mpl::if_<is_same<IsPlanar,use_default>,         is_planar<Iterator>,  IsPlanar>::type::value;
    00456     static const bool step  =mpl::if_<is_same<IsStep  ,use_default>,  iterator_is_step<Iterator>,    IsStep>::type::value;
    00457 public:
    00458     typedef typename iterator_type<channel_t, layout_t, planar, step, mut>::type type;
    00459 };
    00460
    00464 template <typename View, typename T=use_default, typename L=use_default, typename IsPlanar=use_default, typename StepX=use_default, typename IsMutable=use_default>
    00465 class derived_view_type {
    00466     typedef typename  mpl::if_<is_same<T ,use_default>, typename channel_type<View>::type, T>::type channel_t;
    00467     typedef typename  mpl::if_<is_same<L,use_default>,
    00468         layout<typename color_space_type<View>::type, typename channel_mapping_type<View>::type>, L>::type layout_t;
    00469     static const bool mut   =mpl::if_<is_same<IsMutable,use_default>, view_is_mutable<View>, IsMutable>::type::value;
    00470     static const bool planar=mpl::if_<is_same<IsPlanar,use_default>,  is_planar<View>,  IsPlanar>::type::value;
    00471     static const bool step  =mpl::if_<is_same<StepX ,use_default>,  view_is_step_in_x<View>,StepX>::type::value;
    00472 public:
    00473     typedef typename view_type<channel_t, layout_t, planar, step, mut>::type type;
    00474 };
    00475
    00479 template <typename Image, typename T=use_default, typename L=use_default, typename IsPlanar=use_default>
    00480 class derived_image_type {
    00481     typedef typename  mpl::if_<is_same<T ,use_default>, typename channel_type<Image>::type,     T >::type channel_t;
    00482     typedef typename  mpl::if_<is_same<L,use_default>,
    00483         layout<typename color_space_type<Image>::type, typename channel_mapping_type<Image>::type>, L>::type layout_t;
    00484     static const bool planar=mpl::if_<is_same<IsPlanar,use_default>,  is_planar<Image>,  IsPlanar>::type::value;
    00485 public:
    00486     typedef typename image_type<channel_t, layout_t, planar>::type type;
    00487 };
    00488
    00489
    00490
    00491
    00492 } }  // namespace boost::gil
    00493
    00494 #endif