& d) : _n(d._n) {} int _n; // the channel to use result_type operator()(argument_type srcP) const { return result_type(srcP[_n]); } }; template struct __nth_channel_view { private: typedef nth_channel_deref_fn deref_t; typedef typename View::template add_deref AD; public: typedef typename AD::type type; static type make(const View& src, int n) { return AD::make(src, deref_t(n)); } }; } // namespace detail /// \brief Given a source image view type View, returns the type of an image view over a single channel of View /// \ingroup ImageViewTransformationsNthChannel /// /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the /// return view is a single-channel non-step view. /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view. template struct nth_channel_view_type { private: GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept) typedef detail::__nth_channel_view::value> VB; public: typedef typename VB::type type; static type make(const View& src, int n) { return VB::make(src,n); } }; /// \ingroup ImageViewTransformationsNthChannel template typename nth_channel_view_type::type nth_channel_view(const View& src, int n) { return nth_channel_view_type::make(src,n); } /// \defgroup ImageViewTransformationsKthChannel kth_channel_view /// \ingroup ImageViewTransformations /// \brief single-channel (grayscale) view of the K-th channel of a given image_view. The channel index is a template parameter namespace detail { template struct __kth_channel_view_basic; // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images // or images with a step template struct __kth_channel_view_basic { private: typedef typename kth_element_type::type channel_t; public: typedef typename view_type::value>::type type; static type make(const View& src) { typedef typename type::xy_locator locator_t; typedef typename type::x_iterator x_iterator_t; typedef typename iterator_adaptor_get_base::type x_iterator_base_t; x_iterator_t sit(x_iterator_base_t(&at_c(src(0,0))),src.pixels().pixel_size()); return type(src.dimensions(),locator_t(sit, src.pixels().row_size())); } }; // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images) template struct __kth_channel_view_basic { private: typedef typename kth_element_type::type channel_t; public: typedef typename view_type::value>::type type; static type make(const View& src) { typedef typename type::x_iterator x_iterator_t; return interleaved_view(src.width(),src.height(),(x_iterator_t)&at_c(src(0,0)), src.pixels().row_size()); } }; template struct __kth_channel_view; // For basic (memory-based) views dispatch to __kth_channel_view_basic template struct __kth_channel_view { private: typedef typename View::x_iterator src_x_iterator; // Determines whether the channels of a given pixel iterator are adjacent in memory. // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not. BOOST_STATIC_CONSTANT(bool, adjacent= !iterator_is_step::value && (is_planar::value || num_channels::value==1)); public: typedef typename __kth_channel_view_basic::type type; static type make(const View& src) { return __kth_channel_view_basic::make(src); } }; /// \brief Function object that returns a grayscale reference of the K-th channel (specified as a template parameter) of a given reference. Models: PixelDereferenceAdaptorConcept. /// \ingroup PixelDereferenceAdaptorModel /// /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the k-th channel) template // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference) // Examples: pixel, pixel&, const pixel&, planar_pixel_reference, planar_pixel_reference struct kth_channel_deref_fn { BOOST_STATIC_CONSTANT(bool, is_mutable=pixel_is_reference::value && pixel_reference_is_mutable::value); private: typedef typename remove_reference::type src_pixel_t; typedef typename kth_element_type::type channel_t; typedef typename src_pixel_t::const_reference const_ref_t; typedef typename pixel_reference_type::type ref_t; public: typedef kth_channel_deref_fn const_t; typedef typename pixel_value_type::type value_type; typedef typename pixel_reference_type::type const_reference; typedef SrcP argument_type; typedef typename mpl::if_c::type reference; typedef reference result_type; kth_channel_deref_fn() {} template kth_channel_deref_fn(const kth_channel_deref_fn&) {} result_type operator()(argument_type srcP) const { return result_type(at_c(srcP)); } }; template struct __kth_channel_view { private: typedef kth_channel_deref_fn deref_t; typedef typename View::template add_deref AD; public: typedef typename AD::type type; static type make(const View& src) { return AD::make(src, deref_t()); } }; } // namespace detail /// \brief Given a source image view type View, returns the type of an image view over a given channel of View. /// \ingroup ImageViewTransformationsKthChannel /// /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the /// return view is a single-channel non-step view. /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view. template struct kth_channel_view_type { private: GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept) typedef detail::__kth_channel_view::value> VB; public: typedef typename VB::type type; static type make(const View& src) { return VB::make(src); } }; /// \ingroup ImageViewTransformationsKthChannel template typename kth_channel_view_type::type kth_channel_view(const View& src) { return kth_channel_view_type::make(src); } } } // namespace boost::gil #endif