Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # image_view_factory.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_IMAGE_VIEW_FACTORY_HPP
    00014 #define GIL_IMAGE_VIEW_FACTORY_HPP
    00015
    00025
    00027 #include <cassert>
    00028 #include <cstddef>
    00029 #include "gil_config.hpp"
    00030 #include "metafunctions.hpp"
    00031 #include "gray.hpp"
    00032 #include "color_convert.hpp"
    00033
    00037
    00041
    00042 namespace boost { namespace gil {
    00043 struct default_color_converter;
    00044
    00045 template <typename T> struct dynamic_x_step_type;
    00046 template <typename T> struct dynamic_y_step_type;
    00047 template <typename T> struct transposed_type;
    00048
    00051 template <typename View>
    00052 struct dynamic_xy_step_type : public dynamic_y_step_type<typename dynamic_x_step_type<View>::type> {};
    00053
    00056 template <typename View>
    00057 struct dynamic_xy_step_transposed_type : public dynamic_xy_step_type<typename transposed_type<View>::type> {};
    00058
    00059
    00062 template <typename Iterator>
    00063 typename type_from_x_iterator<Iterator>::view_t
    00064 interleaved_view(std::size_t width, std::size_t height,
    00065                  Iterator pixels, std::ptrdiff_t rowsize_in_bytes) {
    00066     typedef typename type_from_x_iterator<Iterator>::view_t RView;
    00067     return RView(width, height, typename RView::locator(pixels, rowsize_in_bytes));
    00068 }
    00069
    00072 template <typename Iterator>
    00073 typename type_from_x_iterator<Iterator>::view_t
    00074 interleaved_view(point2<std::size_t> dim,
    00075                  Iterator pixels, std::ptrdiff_t rowsize_in_bytes) {
    00076     typedef typename type_from_x_iterator<Iterator>::view_t RView;
    00077     return RView(dim, typename RView::locator(pixels, rowsize_in_bytes));
    00078 }
    00079
    00081 //  interleaved_view_get_raw_data, planar_view_get_raw_data - return pointers to the raw data (the channels) of a basic homogeneous view.
    00083
    00084 namespace detail {
    00085     template <typename View, bool IsMutable> struct channel_pointer_type_impl;
    00086
    00087     template <typename View> struct channel_pointer_type_impl<View, true> {
    00088         typedef       typename channel_type<View>::type* type;
    00089     };
    00090     template <typename View> struct channel_pointer_type_impl<View, false> {
    00091         typedef const typename channel_type<View>::type* type;
    00092     };
    00093
    00094     template <typename View> struct channel_pointer_type
    00095         : public channel_pointer_type_impl<View, view_is_mutable<View>::value> {};
    00096 } // namespace detail
    00097
    00100 template <typename HomogeneousView>
    00101 typename detail::channel_pointer_type<HomogeneousView>::type interleaved_view_get_raw_data(const HomogeneousView& view) {
    00102     BOOST_STATIC_ASSERT((!is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value));
    00103     BOOST_STATIC_ASSERT((boost::is_pointer<typename HomogeneousView::x_iterator>::value));
    00104
    00105     return &at_c<0>(view(0,0));
    00106 }
    00107
    00110 template <typename HomogeneousView>
    00111 typename detail::channel_pointer_type<HomogeneousView>::type planar_view_get_raw_data(const HomogeneousView& view, int plane_index) {
    00112     BOOST_STATIC_ASSERT((is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value));
    00113     return dynamic_at_c(view.row_begin(0),plane_index);
    00114 }
    00115
    00116
    00120
    00125 template <typename SrcConstRefP, typename DstP, typename CC=default_color_converter >        // const_reference to the source pixel and destination pixel value
    00126 class color_convert_deref_fn : public deref_base<color_convert_deref_fn<SrcConstRefP,DstP,CC>, DstP, DstP, const DstP&, SrcConstRefP, DstP, false> {
    00127 private:
    00128     CC _cc;                     // color-converter
    00129 public:
    00130     color_convert_deref_fn() {}
    00131     color_convert_deref_fn(CC cc_in) : _cc(cc_in) {}
    00132
    00133     DstP operator()(SrcConstRefP srcP) const {
    00134         DstP dstP;
    00135         _cc(srcP,dstP);
    00136         return dstP;
    00137     }
    00138 };
    00139
    00140 namespace detail {
    00141     // Add color converter upon dereferencing
    00142     template <typename SrcView, typename CC, typename DstP, typename SrcP>
    00143     struct _color_converted_view_type {
    00144     private:
    00145         typedef color_convert_deref_fn<typename SrcView::const_t::reference,DstP,CC> deref_t;
    00146         typedef typename SrcView::template add_deref<deref_t> add_ref_t;
    00147     public:
    00148         typedef typename add_ref_t::type type;
    00149         static type make(const SrcView& sv,CC cc) {return add_ref_t::make(sv,deref_t(cc));}
    00150     };
    00151
    00152     // If the Src view has the same pixel type as the target, there is no need for color conversion
    00153     template <typename SrcView, typename CC, typename DstP>
    00154     struct _color_converted_view_type<SrcView,CC,DstP,DstP> {
    00155         typedef SrcView type;
    00156         static type make(const SrcView& sv,CC) {return sv;}
    00157     };
    00158 } // namespace detail
    00159
    00160
    00163 template <typename SrcView, typename DstP, typename CC=default_color_converter>
    00164 struct color_converted_view_type : public detail::_color_converted_view_type<SrcView,
    00165                                                                              CC,
    00166                                                                              DstP,
    00167                                                                              typename SrcView::value_type> {
    00168     GIL_CLASS_REQUIRE(DstP, boost::gil, MutablePixelConcept)//why does it have to be mutable???
    00169 };
    00170
    00171
    00174 template <typename DstP, typename View, typename CC>
    00175 inline typename color_converted_view_type<View,DstP,CC>::type color_converted_view(const View& src,CC cc) {
    00176     return color_converted_view_type<View,DstP,CC>::make(src,cc);
    00177 }
    00178
    00181 template <typename DstP, typename View>
    00182 inline typename color_converted_view_type<View,DstP>::type
    00183 color_converted_view(const View& src) {
    00184     return color_converted_view<DstP>(src,default_color_converter());
    00185 }
    00186
    00190
    00192 template <typename View>
    00193 inline typename dynamic_y_step_type<View>::type flipped_up_down_view(const View& src) {
    00194     typedef typename dynamic_y_step_type<View>::type RView;
    00195     return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1));
    00196 }
    00197
    00201
    00203 template <typename View>
    00204 inline typename dynamic_x_step_type<View>::type flipped_left_right_view(const View& src) {
    00205     typedef typename dynamic_x_step_type<View>::type RView;
    00206     return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,0),-1,1));
    00207 }
    00208
    00212
    00214 template <typename View>
    00215 inline typename dynamic_xy_step_transposed_type<View>::type transposed_view(const View& src) {
    00216     typedef typename dynamic_xy_step_transposed_type<View>::type RView;
    00217     return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,0),1,1,true));
    00218 }
    00219
    00223
    00225 template <typename View>
    00226 inline typename dynamic_xy_step_transposed_type<View>::type rotated90cw_view(const View& src) {
    00227     typedef typename dynamic_xy_step_transposed_type<View>::type RView;
    00228     return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1,1,true));
    00229 }
    00230
    00234
    00236 template <typename View>
    00237 inline typename dynamic_xy_step_transposed_type<View>::type rotated90ccw_view(const View& src) {
    00238     typedef typename dynamic_xy_step_transposed_type<View>::type RView;
    00239     return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(src.width()-1,0),1,-1,true));
    00240 }
    00241
    00245
    00247 template <typename View>
    00248 inline typename dynamic_xy_step_type<View>::type rotated180_view(const View& src) {
    00249     typedef typename dynamic_xy_step_type<View>::type RView;
    00250     return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,src.height()-1),-1,-1));
    00251 }
    00252
    00256
    00258 template <typename View>
    00259 inline View subimage_view(const View& src, const typename View::point_t& topleft, const typename View::point_t& dimensions) {
    00260     return View(dimensions,src.xy_at(topleft));
    00261 }
    00262
    00264 template <typename View>
    00265 inline View subimage_view(const View& src, int xMin, int yMin, int width, int height) {
    00266     return View(width,height,src.xy_at(xMin,yMin));
    00267 }
    00268
    00272
    00274 template <typename View>
    00275 inline typename dynamic_xy_step_type<View>::type subsampled_view(const View& src, typename View::coord_t xStep, typename View::coord_t yStep) {
    00276     assert(xStep>0 && yStep>0);
    00277     typedef typename dynamic_xy_step_type<View>::type RView;
    00278     return RView((src.width()+(xStep-1))/xStep,(src.height()+(yStep-1))/yStep,
    00279                                           typename RView::xy_locator(src.xy_at(0,0),xStep,yStep));
    00280 }
    00281
    00283 template <typename View>
    00284 inline typename dynamic_xy_step_type<View>::type subsampled_view(const View& src, const typename View::point_t& step) {
    00285     return subsampled_view(src,step.x,step.y);
    00286 }
    00287
    00291
    00292 namespace detail {
    00293     template <typename View, bool AreChannelsTogether> struct __nth_channel_view_basic;
    00294
    00295     // nth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
    00296     // or images with a step
    00297     template <typename View>
    00298     struct __nth_channel_view_basic<View,false> {
    00299         typedef typename view_type<typename channel_type<View>::type, gray_layout_t, false, true, view_is_mutable<View>::value>::type type;
    00300
    00301         static type make(const View& src, int n) {
    00302             typedef typename type::xy_locator                             locator_t;
    00303             typedef typename type::x_iterator                            x_iterator_t;
    00304             typedef typename iterator_adaptor_get_base<x_iterator_t>::type x_iterator_base_t;
    00305             x_iterator_t sit(x_iterator_base_t(&(src(0,0)[n])),src.pixels().pixel_size());
    00306             return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
    00307         }
    00308     };
    00309
    00310     // nth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
    00311     template <typename View>
    00312     struct __nth_channel_view_basic<View,true> {
    00313         typedef typename view_type<typename channel_type<View>::type, gray_layout_t, false, false, view_is_mutable<View>::value>::type type;
    00314         static type make(const View& src, int n) {
    00315             typedef typename type::x_iterator x_iterator_t;
    00316             return interleaved_view(src.width(),src.height(),(x_iterator_t)&(src(0,0)[n]), src.pixels().row_size());
    00317         }
    00318     };
    00319
    00320     template <typename View, bool IsBasic> struct __nth_channel_view;
    00321
    00322     // For basic (memory-based) views dispatch to __nth_channel_view_basic
    00323     template <typename View> struct __nth_channel_view<View,true> {
    00324     private:
    00325         typedef typename View::x_iterator src_x_iterator;
    00326
    00327         // Determines whether the channels of a given pixel iterator are adjacent in memory.
    00328         // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
    00329         BOOST_STATIC_CONSTANT(bool, adjacent=
    00330                               !iterator_is_step<src_x_iterator>::value &&
    00331                               (is_planar<src_x_iterator>::value ||
    00332                               num_channels<View>::value==1));
    00333     public:
    00334         typedef typename __nth_channel_view_basic<View,adjacent>::type type;
    00335
    00336         static type make(const View& src, int n) {
    00337             return __nth_channel_view_basic<View,adjacent>::make(src,n);
    00338         }
    00339     };
    00340
    00345     template <typename SrcP>        // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference)
    00346                                     // Examples: pixel<T,L>, pixel<T,L>&, const pixel<T,L>&, planar_pixel_reference<T&,L>, planar_pixel_reference<const T&,L>
    00347     struct nth_channel_deref_fn {
    00348         BOOST_STATIC_CONSTANT(bool, is_mutable=pixel_is_reference<SrcP>::value && pixel_reference_is_mutable<SrcP>::value);
    00349     private:
    00350         typedef typename remove_reference<SrcP>::type src_pixel_t;
    00351         typedef typename channel_type<src_pixel_t>::type channel_t;
    00352         typedef typename src_pixel_t::const_reference const_ref_t;
    00353         typedef typename pixel_reference_type<channel_t,gray_layout_t,false,is_mutable>::type ref_t;
    00354     public:
    00355         typedef nth_channel_deref_fn<const_ref_t>                                        const_t;
    00356         typedef typename pixel_value_type<channel_t,gray_layout_t>::type                 value_type;
    00357         typedef typename pixel_reference_type<channel_t,gray_layout_t,false,false>::type const_reference;
    00358         typedef SrcP                                                                     argument_type;
    00359         typedef typename mpl::if_c<is_mutable, ref_t, value_type>::type                  reference;
    00360         typedef reference                                                                result_type;
    00361
    00362         nth_channel_deref_fn(int n=0) : _n(n) {}
    00363         template <typename P> nth_channel_deref_fn(const nth_channel_deref_fn<P>& d) : _n(d._n) {}
    00364
    00365         int _n;        // the channel to use
    00366
    00367         result_type operator()(argument_type srcP) const {
    00368             return result_type(srcP[_n]);
    00369         }
    00370     };
    00371
    00372     template <typename View> struct __nth_channel_view<View,false> {
    00373     private:
    00374         typedef nth_channel_deref_fn<typename View::reference> deref_t;
    00375         typedef typename View::template add_deref<deref_t>   AD;
    00376     public:
    00377         typedef typename AD::type type;
    00378         static type make(const View& src, int n) {
    00379             return AD::make(src, deref_t(n));
    00380         }
    00381     };
    00382 } // namespace detail
    00383
    00390 template <typename View>
    00391 struct nth_channel_view_type {
    00392 private:
    00393     GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
    00394     typedef detail::__nth_channel_view<View,view_is_basic<View>::value> VB;
    00395 public:
    00396     typedef typename VB::type type;
    00397     static type make(const View& src, int n) { return VB::make(src,n); }
    00398 };
    00399
    00400
    00402 template <typename View>
    00403 typename nth_channel_view_type<View>::type nth_channel_view(const View& src, int n) {
    00404     return nth_channel_view_type<View>::make(src,n);
    00405 }
    00406
    00407
    00408
    00409
    00410
    00411
    00412
    00416
    00417 namespace detail {
    00418     template <int K, typename View, bool AreChannelsTogether> struct __kth_channel_view_basic;
    00419
    00420     // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
    00421     // or images with a step
    00422     template <int K, typename View>
    00423     struct __kth_channel_view_basic<K,View,false> {
    00424     private:
    00425         typedef typename kth_element_type<typename View::value_type,K>::type channel_t;
    00426     public:
    00427         typedef typename view_type<channel_t, gray_layout_t, false, true, view_is_mutable<View>::value>::type type;
    00428
    00429         static type make(const View& src) {
    00430             typedef typename type::xy_locator                             locator_t;
    00431             typedef typename type::x_iterator                            x_iterator_t;
    00432             typedef typename iterator_adaptor_get_base<x_iterator_t>::type x_iterator_base_t;
    00433             x_iterator_t sit(x_iterator_base_t(&at_c<K>(src(0,0))),src.pixels().pixel_size());
    00434             return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
    00435         }
    00436     };
    00437
    00438     // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
    00439     template <int K, typename View>
    00440     struct __kth_channel_view_basic<K,View,true> {
    00441     private:
    00442         typedef typename kth_element_type<typename View::value_type, K>::type channel_t;
    00443     public:
    00444         typedef typename view_type<channel_t, gray_layout_t, false, false, view_is_mutable<View>::value>::type type;
    00445         static type make(const View& src) {
    00446             typedef typename type::x_iterator x_iterator_t;
    00447             return interleaved_view(src.width(),src.height(),(x_iterator_t)&at_c<K>(src(0,0)), src.pixels().row_size());
    00448         }
    00449     };
    00450
    00451     template <int K, typename View, bool IsBasic> struct __kth_channel_view;
    00452
    00453     // For basic (memory-based) views dispatch to __kth_channel_view_basic
    00454     template <int K, typename View> struct __kth_channel_view<K,View,true> {
    00455     private:
    00456         typedef typename View::x_iterator src_x_iterator;
    00457
    00458         // Determines whether the channels of a given pixel iterator are adjacent in memory.
    00459         // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
    00460         BOOST_STATIC_CONSTANT(bool, adjacent=
    00461                               !iterator_is_step<src_x_iterator>::value &&
    00462                               (is_planar<src_x_iterator>::value ||
    00463                               num_channels<View>::value==1));
    00464     public:
    00465         typedef typename __kth_channel_view_basic<K,View,adjacent>::type type;
    00466
    00467         static type make(const View& src) {
    00468             return __kth_channel_view_basic<K,View,adjacent>::make(src);
    00469         }
    00470     };
    00471
    00476     template <int K, typename SrcP>        // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference)
    00477                                     // Examples: pixel<T,L>, pixel<T,L>&, const pixel<T,L>&, planar_pixel_reference<T&,L>, planar_pixel_reference<const T&,L>
    00478     struct kth_channel_deref_fn {
    00479         BOOST_STATIC_CONSTANT(bool, is_mutable=pixel_is_reference<SrcP>::value && pixel_reference_is_mutable<SrcP>::value);
    00480     private:
    00481         typedef typename remove_reference<SrcP>::type src_pixel_t;
    00482         typedef typename kth_element_type<src_pixel_t, K>::type channel_t;
    00483         typedef typename src_pixel_t::const_reference const_ref_t;
    00484         typedef typename pixel_reference_type<channel_t,gray_layout_t,false,is_mutable>::type ref_t;
    00485     public:
    00486         typedef kth_channel_deref_fn<K,const_ref_t>                               const_t;
    00487         typedef typename pixel_value_type<channel_t,gray_layout_t>::type          value_type;
    00488         typedef typename pixel_reference_type<channel_t,gray_layout_t,false,false>::type const_reference;
    00489         typedef SrcP                                                              argument_type;
    00490         typedef typename mpl::if_c<is_mutable, ref_t, value_type>::type           reference;
    00491         typedef reference                                                         result_type;
    00492
    00493         kth_channel_deref_fn() {}
    00494         template <typename P> kth_channel_deref_fn(const kth_channel_deref_fn<K,P>&) {}
    00495
    00496         result_type operator()(argument_type srcP) const {
    00497             return result_type(at_c<K>(srcP));
    00498         }
    00499     };
    00500
    00501     template <int K, typename View> struct __kth_channel_view<K,View,false> {
    00502     private:
    00503         typedef kth_channel_deref_fn<K,typename View::reference> deref_t;
    00504         typedef typename View::template add_deref<deref_t>   AD;
    00505     public:
    00506         typedef typename AD::type type;
    00507         static type make(const View& src) {
    00508             return AD::make(src, deref_t());
    00509         }
    00510     };
    00511 } // namespace detail
    00512
    00519 template <int K, typename View>
    00520 struct kth_channel_view_type {
    00521 private:
    00522     GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
    00523     typedef detail::__kth_channel_view<K,View,view_is_basic<View>::value> VB;
    00524 public:
    00525     typedef typename VB::type type;
    00526     static type make(const View& src) { return VB::make(src); }
    00527 };
    00528
    00530 template <int K, typename View>
    00531 typename kth_channel_view_type<K,View>::type kth_channel_view(const View& src) {
    00532     return kth_channel_view_type<K,View>::make(src);
    00533 }
    00534
    00535 } }  // namespace boost::gil
    00536
    00537 #endif