Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # color_base.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://stlab.adobe.com/gil for most recent version including documentation.
    00009 */
    00010
    00011 /*************************************************************************************************/
    00012
    00013 #ifndef GIL_COLOR_BASE_HPP
    00014 #define GIL_COLOR_BASE_HPP
    00015
    00024
    00025 #include <cassert>
    00026 #include <boost/mpl/range_c.hpp>
    00027 #include <boost/mpl/size.hpp>
    00028 #include <boost/mpl/vector_c.hpp>
    00029 #include <boost/type_traits.hpp>
    00030 #include <boost/utility/enable_if.hpp>
    00031
    00032 #include "gil_config.hpp"
    00033 #include "utilities.hpp"
    00034 #include "gil_concept.hpp"
    00035
    00036 namespace boost { namespace gil {
    00037
    00038 // Forward-declare
    00039 template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff);
    00040
    00041 // Forward-declare semantic_at_c
    00042 template <int K, typename ColorBase>
    00043 typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type semantic_at_c(ColorBase& p);
    00044 template <int K, typename ColorBase>
    00045 typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p);
    00046
    00047 // Forward declare element_reference_type
    00048 template <typename ColorBase> struct element_reference_type;
    00049 template <typename ColorBase> struct element_const_reference_type;
    00050 template <typename ColorBase, int K> struct kth_element_type;
    00051 template <typename ColorBase, int K> struct kth_element_type<const ColorBase,K> : public kth_element_type<ColorBase,K> {};
    00052 template <typename ColorBase, int K> struct kth_element_reference_type;
    00053 template <typename ColorBase, int K> struct kth_element_reference_type<const ColorBase,K> : public kth_element_reference_type<ColorBase,K> {};
    00054 template <typename ColorBase, int K> struct kth_element_const_reference_type;
    00055 template <typename ColorBase, int K> struct kth_element_const_reference_type<const ColorBase,K> : public kth_element_const_reference_type<ColorBase,K> {};
    00056
    00057 namespace detail {
    00058
    00059 template <typename DstLayout, typename SrcLayout, int K>
    00060 struct mapping_transform
    00061     : public mpl::at<typename SrcLayout::channel_mapping_t,
    00062                      typename detail::type_to_index<typename DstLayout::channel_mapping_t,mpl::integral_c<int,K> >::type
    00063                            >::type {};
    00064
    00069
    00070
    00073 template <typename Element, typename Layout>
    00074 struct homogeneous_color_base<Element,Layout,1> {
    00075 private:
    00076     Element _v0;
    00077 public:
    00078     typedef Layout layout_t;
    00079     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<0>)       { return _v0; }
    00080     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
    00081
    00082     homogeneous_color_base() {}
    00083     homogeneous_color_base(Element v) : _v0(v) {}
    00084
    00085     // grayscale pixel values are convertible to channel type
    00086     operator Element () const { return _v0; }
    00087
    00088     template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,1>& c) : _v0(at_c<0>(c)) {}
    00089 };
    00090
    00091
    00094 template <typename Element, typename Layout>
    00095 struct homogeneous_color_base<Element,Layout,2> {
    00096 private:
    00097     Element _v0, _v1;
    00098 public:
    00099     typedef Layout layout_t;
    00100     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<0>)       { return _v0; }
    00101     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
    00102     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<1>)       { return _v1; }
    00103     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
    00104
    00105     homogeneous_color_base() {}
    00106     explicit homogeneous_color_base(Element v) : _v0(v), _v1(v) {}
    00107     homogeneous_color_base(Element v0, Element v1) : _v0(v0), _v1(v1) {}
    00108
    00109     template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,2>& c) :
    00110         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00111         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
    00112
    00113     // Support for l-value reference proxy copy construction
    00114     template <typename E2, typename L2> homogeneous_color_base(      homogeneous_color_base<E2,L2,2>& c) :
    00115         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00116         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
    00117
    00118     // Support for planar_pixel_iterator construction and dereferencing
    00119     template <typename P> homogeneous_color_base(P* p,bool) :
    00120         _v0(&semantic_at_c<0>(*p)),
    00121         _v1(&semantic_at_c<1>(*p)) {}
    00122     template <typename Ref> Ref deref() const {
    00123         return Ref(*semantic_at_c<0>(*this),
    00124                    *semantic_at_c<1>(*this)); }
    00125
    00126     // Support for planar_pixel_reference offset constructor
    00127     template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
    00128         : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
    00129           _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)) {}
    00130
    00131     // Support for planar_pixel_reference operator[]
    00132     Element at_c_dynamic(std::size_t i) const {
    00133         if (i==0) return _v0;
    00134         return _v1;
    00135     }
    00136 };
    00137
    00140 template <typename Element, typename Layout>
    00141 struct homogeneous_color_base<Element,Layout,3> {
    00142 private:
    00143     Element _v0, _v1, _v2;
    00144 public:
    00145     typedef Layout layout_t;
    00146     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<0>)       { return _v0; }
    00147     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
    00148     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<1>)       { return _v1; }
    00149     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
    00150     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<2>)       { return _v2; }
    00151     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
    00152
    00153     homogeneous_color_base() {}
    00154     explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v) {}
    00155     homogeneous_color_base(Element v0, Element v1, Element v2) : _v0(v0), _v1(v1), _v2(v2) {}
    00156
    00157     template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,3>& c) :
    00158         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00159         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
    00160         _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
    00161
    00162     // Support for l-value reference proxy copy construction
    00163     template <typename E2, typename L2> homogeneous_color_base(      homogeneous_color_base<E2,L2,3>& c) :
    00164         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00165         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
    00166         _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
    00167
    00168     // Support for planar_pixel_iterator construction and dereferencing
    00169     template <typename P> homogeneous_color_base(P* p,bool) :
    00170         _v0(&semantic_at_c<0>(*p)),
    00171         _v1(&semantic_at_c<1>(*p)),
    00172         _v2(&semantic_at_c<2>(*p)) {}
    00173     template <typename Ref> Ref deref() const {
    00174         return Ref(*semantic_at_c<0>(*this),
    00175                    *semantic_at_c<1>(*this),
    00176                    *semantic_at_c<2>(*this)); }
    00177
    00178     // Support for planar_pixel_reference offset constructor
    00179     template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
    00180         : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
    00181           _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
    00182           _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)) {}
    00183
    00184     // Support for planar_pixel_reference operator[]
    00185     Element at_c_dynamic(std::size_t i) const {
    00186         switch (i) {
    00187             case 0: return _v0;
    00188             case 1: return _v1;
    00189         }
    00190         return _v2;
    00191     }
    00192 };
    00193
    00196 template <typename Element, typename Layout>
    00197 struct homogeneous_color_base<Element,Layout,4> {
    00198 private:
    00199     Element _v0, _v1, _v2, _v3;
    00200 public:
    00201     typedef Layout layout_t;
    00202     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<0>)       { return _v0; }
    00203     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
    00204     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<1>)       { return _v1; }
    00205     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
    00206     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<2>)       { return _v2; }
    00207     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
    00208     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<3>)       { return _v3; }
    00209     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
    00210     homogeneous_color_base() {}
    00211     explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v) {}
    00212     homogeneous_color_base(Element v0, Element v1, Element v2, Element v3) : _v0(v0), _v1(v1), _v2(v2), _v3(v3) {}
    00213
    00214     template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,4>& c) :
    00215         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00216         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
    00217         _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
    00218         _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
    00219
    00220     // Support for l-value reference proxy copy construction
    00221     template <typename E2, typename L2> homogeneous_color_base(      homogeneous_color_base<E2,L2,4>& c) :
    00222         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00223         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
    00224         _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
    00225         _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
    00226
    00227     // Support for planar_pixel_iterator construction and dereferencing
    00228     template <typename P> homogeneous_color_base(P* p,bool) :
    00229         _v0(&semantic_at_c<0>(*p)),
    00230         _v1(&semantic_at_c<1>(*p)),
    00231         _v2(&semantic_at_c<2>(*p)),
    00232         _v3(&semantic_at_c<3>(*p)) {}
    00233
    00234     template <typename Ref> Ref deref() const {
    00235         return Ref(*semantic_at_c<0>(*this),
    00236                    *semantic_at_c<1>(*this),
    00237                    *semantic_at_c<2>(*this),
    00238                    *semantic_at_c<3>(*this)); }
    00239
    00240     // Support for planar_pixel_reference offset constructor
    00241     template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
    00242         : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
    00243           _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
    00244           _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
    00245           _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)) {}
    00246
    00247     // Support for planar_pixel_reference operator[]
    00248     Element at_c_dynamic(std::size_t i) const {
    00249         switch (i) {
    00250             case 0: return _v0;
    00251             case 1: return _v1;
    00252             case 2: return _v2;
    00253         }
    00254         return _v3;
    00255     }
    00256 };
    00257
    00260 template <typename Element, typename Layout>
    00261 struct homogeneous_color_base<Element,Layout,5> {
    00262 private:
    00263     Element _v0, _v1, _v2, _v3, _v4;
    00264 public:
    00265     typedef Layout layout_t;
    00266     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<0>)       { return _v0; }
    00267     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
    00268     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<1>)       { return _v1; }
    00269     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
    00270     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<2>)       { return _v2; }
    00271     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
    00272     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<3>)       { return _v3; }
    00273     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
    00274     typename element_reference_type<homogeneous_color_base>::type       at(mpl::int_<4>)       { return _v4; }
    00275     typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<4>) const { return _v4; }
    00276     homogeneous_color_base() {}
    00277     explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v), _v4(v) {}
    00278     homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4) : _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4) {}
    00279
    00280     template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,5>& c) :
    00281         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00282         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
    00283         _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
    00284         _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)),
    00285         _v4(at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
    00286
    00287     // Support for l-value reference proxy copy construction
    00288     template <typename E2, typename L2> homogeneous_color_base(      homogeneous_color_base<E2,L2,5>& c) :
    00289         _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
    00290         _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
    00291         _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
    00292         _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)),
    00293         _v4(at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
    00294
    00295     // Support for planar_pixel_iterator construction and dereferencing
    00296     template <typename P> homogeneous_color_base(P* p,bool) :
    00297         _v0(&semantic_at_c<0>(*p)),
    00298         _v1(&semantic_at_c<1>(*p)),
    00299         _v2(&semantic_at_c<2>(*p)),
    00300         _v3(&semantic_at_c<3>(*p)),
    00301         _v4(&semantic_at_c<4>(*p)) {}
    00302
    00303     template <typename Ref> Ref deref() const {
    00304         return Ref(*semantic_at_c<0>(*this),
    00305                    *semantic_at_c<1>(*this),
    00306                    *semantic_at_c<2>(*this),
    00307                    *semantic_at_c<3>(*this),
    00308                    *semantic_at_c<4>(*this)); }
    00309
    00310     // Support for planar_pixel_reference offset constructor
    00311     template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
    00312         : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
    00313           _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
    00314           _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
    00315           _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)),
    00316           _v4(*memunit_advanced(semantic_at_c<4>(ptr),diff)) {}
    00317
    00318     // Support for planar_pixel_reference operator[]
    00319     Element at_c_dynamic(std::size_t i) const {
    00320         switch (i) {
    00321             case 0: return _v0;
    00322             case 1: return _v1;
    00323             case 2: return _v2;
    00324             case 3: return _v3;
    00325         }
    00326         return _v4;
    00327     }
    00328 };
    00329
    00330 // The following way of casting adjacent channels (the contents of color_base) into an array appears to be unsafe
    00331 // -- there is no guarantee that the compiler won't add any padding between adjacent channels.
    00332 // Note, however, that GIL _must_ be compiled with compiler settings ensuring there is no padding in the color base structs.
    00333 // This is because the color base structs must model the interleaved organization in memory. In other words, the client may
    00334 // have existing RGB image in the form "RGBRGBRGB..." and we must be able to represent it with an array of RGB color bases (i.e. RGB pixels)
    00335 // with no padding. We have tested with char/int/float/double channels on gcc and VC and have so far discovered no problem.
    00336 // We have even tried using strange channels consisting of short + char (3 bytes). With the default 4-byte alignment on VC, the size
    00337 // of this channel is padded to 4 bytes, so an RGB pixel of it will be 4x3=12 bytes. The code below will still work properly.
    00338 // However, the client must nevertheless ensure that proper compiler settings are used for their compiler and their channel types.
    00339
    00340 template <typename Element, typename Layout, int K>
    00341 typename element_reference_type<homogeneous_color_base<Element,Layout,K> >::type
    00342 dynamic_at_c(homogeneous_color_base<Element,Layout,K>& cb, std::size_t i) {
    00343     assert(i<K);
    00344     return (gil_reinterpret_cast<Element*>(&cb))[i];
    00345 }
    00346
    00347 template <typename Element, typename Layout, int K>
    00348 typename element_const_reference_type<homogeneous_color_base<Element,Layout,K> >::type
    00349 dynamic_at_c(const homogeneous_color_base<Element,Layout,K>& cb, std::size_t i) {
    00350     assert(i<K);
    00351     return (gil_reinterpret_cast_c<const Element*>(&cb))[i];
    00352 }
    00353
    00354 template <typename Element, typename Layout, int K>
    00355 typename element_reference_type<homogeneous_color_base<Element&,Layout,K> >::type
    00356 dynamic_at_c(const homogeneous_color_base<Element&,Layout,K>& cb, std::size_t i) {
    00357     assert(i<K);
    00358     return cb.at_c_dynamic(i);
    00359 }
    00360
    00361 template <typename Element, typename Layout, int K>
    00362 typename element_const_reference_type<homogeneous_color_base<const Element&,Layout,K> >::type
    00363 dynamic_at_c(const homogeneous_color_base<const Element&,Layout,K>& cb, std::size_t i) {
    00364     assert(i<K);
    00365     return cb.at_c_dynamic(i);
    00366 }
    00367
    00368
    00369 } // namespace detail
    00370
    00371 template <typename Element, typename Layout, int K1, int K>
    00372 struct kth_element_type<detail::homogeneous_color_base<Element,Layout,K1>, K> {
    00373     typedef Element type;
    00374 };
    00375
    00376 template <typename Element, typename Layout, int K1, int K>
    00377 struct kth_element_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<Element> {};
    00378
    00379 template <typename Element, typename Layout, int K1, int K>
    00380 struct kth_element_const_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<typename add_const<Element>::type> {};
    00381
    00384 template <int K, typename E, typename L, int N> inline
    00385 typename add_reference<E>::type
    00386 at_c(      detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
    00387
    00390 template <int K, typename E, typename L, int N> inline
    00391 typename add_reference<typename add_const<E>::type>::type
    00392 at_c(const detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
    00393
    00394 namespace detail {
    00395     struct swap_fn {
    00396         template <typename T> void operator()(T& x, T& y) const {
    00397             using std::swap;
    00398             swap(x,y);
    00399         }
    00400     };
    00401 }
    00402 template <typename E, typename L, int N> inline
    00403 void swap(detail::homogeneous_color_base<E,L,N>& x, detail::homogeneous_color_base<E,L,N>& y) {
    00404     static_for_each(x,y,detail::swap_fn());
    00405 }
    00406
    00407
    00408 } }  // namespace boost::gil
    00409
    00410 #endif