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

Generated on Sat May 2 13:50:14 2009 for Generic Image Library by  doxygen 1.5.6