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