| /* |
| Copyright 2005-2007 Adobe Systems Incorporated |
| |
| Use, modification and distribution are subject to the Boost Software License, |
| Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| http://www.boost.org/LICENSE_1_0.txt). |
| |
| See http://opensource.adobe.com/gil for most recent version including documentation. |
| */ |
| |
| /*************************************************************************************************/ |
| |
| #ifndef GIL_COLOR_BASE_ALGORITHM_HPP |
| #define GIL_COLOR_BASE_ALGORITHM_HPP |
| |
| //////////////////////////////////////////////////////////////////////////////////////// |
| /// \file |
| /// \brief pixel related algorithms |
| /// \author Lubomir Bourdev and Hailin Jin \n |
| /// Adobe Systems Incorporated |
| /// \date 2005-2007 \n Last updated on February 16, 2007 |
| /// |
| //////////////////////////////////////////////////////////////////////////////////////// |
| |
| #include <algorithm> |
| #include <boost/type_traits.hpp> |
| #include <boost/utility/enable_if.hpp> |
| #include <boost/mpl/contains.hpp> |
| #include <boost/mpl/at.hpp> |
| #include "gil_config.hpp" |
| #include "gil_concept.hpp" |
| #include "utilities.hpp" |
| |
| namespace boost { namespace gil { |
| |
| |
| /////////////////////////////////////// |
| /// |
| /// size: Semantic channel size |
| /// |
| /////////////////////////////////////// |
| |
| /** |
| \defgroup ColorBaseAlgorithmSize size |
| \ingroup ColorBaseAlgorithm |
| \brief Returns an MPL integral type specifying the number of elements in a color base |
| |
| Example: |
| \code |
| BOOST_STATIC_ASSERT((size<rgb8_pixel_t>::value == 3)); |
| BOOST_STATIC_ASSERT((size<cmyk8_planar_ptr_t>::value == 4)); |
| \endcode |
| */ |
| |
| /// \brief Returns an MPL integral type specifying the number of elements in a color base |
| /// \ingroup ColorBaseAlgorithmSize |
| template <typename ColorBase> |
| struct size : public mpl::size<typename ColorBase::layout_t::color_space_t> {}; |
| |
| /////////////////////////////////////// |
| /// |
| /// semantic_at_c: Semantic channel accessors |
| /// |
| /////////////////////////////////////// |
| |
| /** |
| \defgroup ColorBaseAlgorithmSemanticAtC kth_semantic_element_type, kth_semantic_element_reference_type, kth_semantic_element_const_reference_type, semantic_at_c |
| \ingroup ColorBaseAlgorithm |
| \brief Support for accessing the elements of a color base by semantic index |
| |
| The semantic index of an element is the index of its color in the color space. Semantic indexing allows for proper pairing of elements of color bases |
| independent on their layout. For example, red is the first semantic element of a color base regardless of whether it has an RGB layout or a BGR layout. |
| All GIL color base algorithms taking multiple color bases use semantic indexing to access their elements. |
| |
| Example: |
| \code |
| // 16-bit BGR pixel, 4 bits for the blue, 3 bits for the green, 2 bits for the red channel and 7 unused bits |
| typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,4,3,2>, bgr_layout_t>::type bgr432_pixel_t; |
| |
| // A reference to its red channel. Although the red channel is the third, its semantic index is 0 in the RGB color space |
| typedef kth_semantic_element_reference_type<bgr432_pixel_t, 0>::type red_channel_reference_t; |
| |
| // Initialize the pixel to black |
| bgr432_pixel_t red_pixel(0,0,0); |
| |
| // Set the red channel to 100% |
| red_channel_reference_t red_channel = semantic_at_c<0>(red_pixel); |
| red_channel = channel_traits<red_channel_reference_t>::max_value(); |
| |
| \endcode |
| */ |
| /// \brief Specifies the type of the K-th semantic element of a color base |
| /// \ingroup ColorBaseAlgorithmSemanticAtC |
| template <typename ColorBase, int K> struct kth_semantic_element_type { |
| BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value)); |
| typedef typename kth_element_type<ColorBase, semantic_index>::type type; |
| }; |
| |
| /// \brief Specifies the return type of the mutable semantic_at_c<K>(color_base); |
| /// \ingroup ColorBaseAlgorithmSemanticAtC |
| template <typename ColorBase, int K> struct kth_semantic_element_reference_type { |
| BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value)); |
| typedef typename kth_element_reference_type<ColorBase,semantic_index>::type type; |
| static type get(ColorBase& cb) { return gil::at_c<semantic_index>(cb); } |
| }; |
| |
| /// \brief Specifies the return type of the constant semantic_at_c<K>(color_base); |
| /// \ingroup ColorBaseAlgorithmSemanticAtC |
| template <typename ColorBase, int K> struct kth_semantic_element_const_reference_type { |
| BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value)); |
| typedef typename kth_element_const_reference_type<ColorBase,semantic_index>::type type; |
| static type get(const ColorBase& cb) { return gil::at_c<semantic_index>(cb); } |
| }; |
| |
| /// \brief A mutable accessor to the K-th semantic element of a color base |
| /// \ingroup ColorBaseAlgorithmSemanticAtC |
| template <int K, typename ColorBase> inline |
| typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type |
| semantic_at_c(ColorBase& p) { |
| return kth_semantic_element_reference_type<ColorBase,K>::get(p); |
| } |
| |
| /// \brief A constant accessor to the K-th semantic element of a color base |
| /// \ingroup ColorBaseAlgorithmSemanticAtC |
| template <int K, typename ColorBase> inline |
| typename kth_semantic_element_const_reference_type<ColorBase,K>::type |
| semantic_at_c(const ColorBase& p) { |
| return kth_semantic_element_const_reference_type<ColorBase,K>::get(p); |
| } |
| |
| /////////////////////////////////////// |
| /// |
| /// get_color: Named channel accessors |
| /// |
| /////////////////////////////////////// |
| |
| /** |
| \defgroup ColorBaseAlgorithmColor color_element_type, color_element_reference_type, color_element_const_reference_type, get_color, contains_color |
| \ingroup ColorBaseAlgorithm |
| \brief Support for accessing the elements of a color base by color name |
| |
| Example: A function that takes a generic pixel containing a red channel and sets it to 100%: |
| |
| \code |
| template <typename Pixel> |
| void set_red_to_max(Pixel& pixel) { |
| boost::function_requires<MutablePixelConcept<Pixel> >(); |
| BOOST_STATIC_ASSERT((contains_color<Pixel, red_t>::value)); |
| |
| typedef typename color_element_type<Pixel, red_t>::type red_channel_t; |
| get_color(pixel, red_t()) = channel_traits<red_channel_t>::max_value(); |
| } |
| \endcode |
| */ |
| |
| /// \brief A predicate metafunction determining whether a given color base contains a given color |
| /// \ingroup ColorBaseAlgorithmColor |
| template <typename ColorBase, typename Color> |
| struct contains_color : public mpl::contains<typename ColorBase::layout_t::color_space_t,Color> {}; |
| |
| template <typename ColorBase, typename Color> |
| struct color_index_type : public detail::type_to_index<typename ColorBase::layout_t::color_space_t,Color> {}; |
| |
| /// \brief Specifies the type of the element associated with a given color tag |
| /// \ingroup ColorBaseAlgorithmColor |
| template <typename ColorBase, typename Color> |
| struct color_element_type : public kth_semantic_element_type<ColorBase,color_index_type<ColorBase,Color>::value> {}; |
| |
| /// \brief Specifies the return type of the mutable element accessor by color name, get_color(color_base, Color()); |
| /// \ingroup ColorBaseAlgorithmColor |
| template <typename ColorBase, typename Color> |
| struct color_element_reference_type : public kth_semantic_element_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {}; |
| |
| /// \brief Specifies the return type of the constant element accessor by color name, get_color(color_base, Color()); |
| /// \ingroup ColorBaseAlgorithmColor |
| template <typename ColorBase, typename Color> |
| struct color_element_const_reference_type : public kth_semantic_element_const_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {}; |
| |
| /// \brief Mutable accessor to the element associated with a given color name |
| /// \ingroup ColorBaseAlgorithmColor |
| template <typename ColorBase, typename Color> |
| typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) { |
| return color_element_reference_type<ColorBase,Color>::get(cb); |
| } |
| |
| /// \brief Constant accessor to the element associated with a given color name |
| /// \ingroup ColorBaseAlgorithmColor |
| template <typename ColorBase, typename Color> |
| typename color_element_const_reference_type<ColorBase,Color>::type get_color(const ColorBase& cb, Color=Color()) { |
| return color_element_const_reference_type<ColorBase,Color>::get(cb); |
| } |
| |
| /////////////////////////////////////// |
| /// |
| /// element_type, element_reference_type, element_const_reference_type: Support for homogeneous color bases |
| /// |
| /////////////////////////////////////// |
| |
| /** |
| \defgroup ColorBaseAlgorithmHomogeneous element_type, element_reference_type, element_const_reference_type |
| \ingroup ColorBaseAlgorithm |
| \brief Types for homogeneous color bases |
| |
| Example: |
| \code |
| typedef element_type<rgb8c_planar_ptr_t>::type element_t; |
| BOOST_STATIC_ASSERT((boost::is_same<element_t, const bits8*>::value)); |
| \endcode |
| */ |
| /// \brief Specifies the element type of a homogeneous color base |
| /// \ingroup ColorBaseAlgorithmHomogeneous |
| template <typename ColorBase> |
| struct element_type : public kth_element_type<ColorBase, 0> {}; |
| |
| /// \brief Specifies the return type of the mutable element accessor at_c of a homogeneous color base |
| /// \ingroup ColorBaseAlgorithmHomogeneous |
| template <typename ColorBase> |
| struct element_reference_type : public kth_element_reference_type<ColorBase, 0> {}; |
| |
| /// \brief Specifies the return type of the constant element accessor at_c of a homogeneous color base |
| /// \ingroup ColorBaseAlgorithmHomogeneous |
| template <typename ColorBase> |
| struct element_const_reference_type : public kth_element_const_reference_type<ColorBase, 0> {}; |
| |
| |
| namespace detail { |
| |
| // compile-time recursion for per-element operations on color bases |
| template <int N> |
| struct element_recursion { |
| //static_equal |
| template <typename P1,typename P2> |
| static bool static_equal(const P1& p1, const P2& p2) { |
| return element_recursion<N-1>::static_equal(p1,p2) && |
| semantic_at_c<N-1>(p1)==semantic_at_c<N-1>(p2); |
| } |
| //static_copy |
| template <typename P1,typename P2> |
| static void static_copy(const P1& p1, P2& p2) { |
| element_recursion<N-1>::static_copy(p1,p2); |
| semantic_at_c<N-1>(p2)=semantic_at_c<N-1>(p1); |
| } |
| //static_fill |
| template <typename P,typename T2> |
| static void static_fill(P& p, T2 v) { |
| element_recursion<N-1>::static_fill(p,v); |
| semantic_at_c<N-1>(p)=v; |
| } |
| //static_generate |
| template <typename Dst,typename Op> |
| static void static_generate(Dst& dst, Op op) { |
| element_recursion<N-1>::static_generate(dst,op); |
| semantic_at_c<N-1>(dst)=op(); |
| } |
| //static_for_each with one source |
| template <typename P1,typename Op> |
| static Op static_for_each(P1& p1, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,op)); |
| op2(semantic_at_c<N-1>(p1)); |
| return op2; |
| } |
| template <typename P1,typename Op> |
| static Op static_for_each(const P1& p1, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,op)); |
| op2(semantic_at_c<N-1>(p1)); |
| return op2; |
| } |
| //static_for_each with two sources |
| template <typename P1,typename P2,typename Op> |
| static Op static_for_each(P1& p1, P2& p2, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename Op> |
| static Op static_for_each(P1& p1, const P2& p2, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename Op> |
| static Op static_for_each(const P1& p1, P2& p2, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename Op> |
| static Op static_for_each(const P1& p1, const P2& p2, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2)); |
| return op2; |
| } |
| //static_for_each with three sources |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(P1& p1, P2& p2, P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(P1& p1, P2& p2, const P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(P1& p1, const P2& p2, P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(P1& p1, const P2& p2, const P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(const P1& p1, P2& p2, P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(const P1& p1, P2& p2, const P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(const P1& p1, const P2& p2, P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(const P1& p1, const P2& p2, const P3& p3, Op op) { |
| Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op)); |
| op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3)); |
| return op2; |
| } |
| //static_transform with one source |
| template <typename P1,typename Dst,typename Op> |
| static Op static_transform(P1& src, Dst& dst, Op op) { |
| Op op2(element_recursion<N-1>::static_transform(src,dst,op)); |
| semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src)); |
| return op2; |
| } |
| template <typename P1,typename Dst,typename Op> |
| static Op static_transform(const P1& src, Dst& dst, Op op) { |
| Op op2(element_recursion<N-1>::static_transform(src,dst,op)); |
| semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src)); |
| return op2; |
| } |
| //static_transform with two sources |
| template <typename P1,typename P2,typename Dst,typename Op> |
| static Op static_transform(P1& src1, P2& src2, Dst& dst, Op op) { |
| Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op)); |
| semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename Dst,typename Op> |
| static Op static_transform(P1& src1, const P2& src2, Dst& dst, Op op) { |
| Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op)); |
| semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename Dst,typename Op> |
| static Op static_transform(const P1& src1, P2& src2, Dst& dst, Op op) { |
| Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op)); |
| semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2)); |
| return op2; |
| } |
| template <typename P1,typename P2,typename Dst,typename Op> |
| static Op static_transform(const P1& src1, const P2& src2, Dst& dst, Op op) { |
| Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op)); |
| semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2)); |
| return op2; |
| } |
| }; |
| |
| // Termination condition of the compile-time recursion for element operations on a color base |
| template<> struct element_recursion<0> { |
| //static_equal |
| template <typename P1,typename P2> |
| static bool static_equal(const P1&, const P2&) { return true; } |
| //static_copy |
| template <typename P1,typename P2> |
| static void static_copy(const P1&, const P2&) {} |
| //static_fill |
| template <typename P, typename T2> |
| static void static_fill(const P&, T2) {} |
| //static_generate |
| template <typename Dst,typename Op> |
| static void static_generate(const Dst&,Op){} |
| //static_for_each with one source |
| template <typename P1,typename Op> |
| static Op static_for_each(const P1&,Op op){return op;} |
| //static_for_each with two sources |
| template <typename P1,typename P2,typename Op> |
| static Op static_for_each(const P1&,const P2&,Op op){return op;} |
| //static_for_each with three sources |
| template <typename P1,typename P2,typename P3,typename Op> |
| static Op static_for_each(const P1&,const P2&,const P3&,Op op){return op;} |
| //static_transform with one source |
| template <typename P1,typename Dst,typename Op> |
| static Op static_transform(const P1&,const Dst&,Op op){return op;} |
| //static_transform with two sources |
| template <typename P1,typename P2,typename Dst,typename Op> |
| static Op static_transform(const P1&,const P2&,const Dst&,Op op){return op;} |
| }; |
| |
| // std::min and std::max don't have the mutable overloads... |
| template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; } |
| template <typename Q> inline Q& mutable_min( Q& x, Q& y) { return x<y ? x : y; } |
| template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; } |
| template <typename Q> inline Q& mutable_max( Q& x, Q& y) { return x<y ? y : x; } |
| |
| |
| // compile-time recursion for min/max element |
| template <int N> |
| struct min_max_recur { |
| template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { |
| return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p)); |
| } |
| template <typename P> static typename element_reference_type<P>::type max_( P& p) { |
| return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p)); |
| } |
| template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { |
| return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p)); |
| } |
| template <typename P> static typename element_reference_type<P>::type min_( P& p) { |
| return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p)); |
| } |
| }; |
| |
| // termination condition of the compile-time recursion for min/max element |
| template <> |
| struct min_max_recur<1> { |
| template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { return semantic_at_c<0>(p); } |
| template <typename P> static typename element_reference_type<P>::type max_( P& p) { return semantic_at_c<0>(p); } |
| template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { return semantic_at_c<0>(p); } |
| template <typename P> static typename element_reference_type<P>::type min_( P& p) { return semantic_at_c<0>(p); } |
| }; |
| } // namespace detail |
| |
| |
| /** |
| \defgroup ColorBaseAlgorithmMinMax static_min, static_max |
| \ingroup ColorBaseAlgorithm |
| \brief Equivalents to std::min_element and std::max_element for homogeneous color bases |
| |
| Example: |
| \code |
| rgb8_pixel_t pixel(10,20,30); |
| assert(pixel[2] == 30); |
| static_max(pixel) = static_min(pixel); |
| assert(pixel[2] == 10); |
| \endcode |
| \{ |
| */ |
| |
| template <typename P> |
| GIL_FORCEINLINE |
| typename element_const_reference_type<P>::type static_max(const P& p) { return detail::min_max_recur<size<P>::value>::max_(p); } |
| |
| template <typename P> |
| GIL_FORCEINLINE |
| typename element_reference_type<P>::type static_max( P& p) { return detail::min_max_recur<size<P>::value>::max_(p); } |
| |
| template <typename P> |
| GIL_FORCEINLINE |
| typename element_const_reference_type<P>::type static_min(const P& p) { return detail::min_max_recur<size<P>::value>::min_(p); } |
| |
| template <typename P> |
| GIL_FORCEINLINE |
| typename element_reference_type<P>::type static_min( P& p) { return detail::min_max_recur<size<P>::value>::min_(p); } |
| /// \} |
| |
| /** |
| \defgroup ColorBaseAlgorithmEqual static_equal |
| \ingroup ColorBaseAlgorithm |
| \brief Equivalent to std::equal. Pairs the elements semantically |
| |
| Example: |
| \code |
| rgb8_pixel_t rgb_red(255,0,0); |
| bgr8_pixel_t bgr_red(0,0,255); |
| assert(rgb_red[0]==255 && bgr_red[0]==0); |
| |
| assert(static_equal(rgb_red,bgr_red)); |
| assert(rgb_red==bgr_red); // operator== invokes static_equal |
| \endcode |
| \{ |
| */ |
| |
| template <typename P1,typename P2> |
| GIL_FORCEINLINE |
| bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); } |
| |
| /// \} |
| |
| /** |
| \defgroup ColorBaseAlgorithmCopy static_copy |
| \ingroup ColorBaseAlgorithm |
| \brief Equivalent to std::copy. Pairs the elements semantically |
| |
| Example: |
| \code |
| rgb8_pixel_t rgb_red(255,0,0); |
| bgr8_pixel_t bgr_red; |
| static_copy(rgb_red, bgr_red); // same as bgr_red = rgb_red |
| |
| assert(rgb_red[0] == 255 && bgr_red[0] == 0); |
| assert(rgb_red == bgr_red); |
| \endcode |
| \{ |
| */ |
| |
| template <typename Src,typename Dst> |
| GIL_FORCEINLINE |
| void static_copy(const Src& src, Dst& dst) { detail::element_recursion<size<Dst>::value>::static_copy(src,dst); } |
| |
| /// \} |
| |
| /** |
| \defgroup ColorBaseAlgorithmFill static_fill |
| \ingroup ColorBaseAlgorithm |
| \brief Equivalent to std::fill. |
| |
| Example: |
| \code |
| rgb8_pixel_t p; |
| static_fill(p, 10); |
| assert(p == rgb8_pixel_t(10,10,10)); |
| \endcode |
| \{ |
| */ |
| template <typename P,typename V> |
| GIL_FORCEINLINE |
| void static_fill(P& p, const V& v) { detail::element_recursion<size<P>::value>::static_fill(p,v); } |
| /// \} |
| |
| /** |
| \defgroup ColorBaseAlgorithmGenerate static_generate |
| \ingroup ColorBaseAlgorithm |
| \brief Equivalent to std::generate. |
| |
| Example: Set each channel of a pixel to its semantic index. The channels must be assignable from an integer. |
| \code |
| struct consecutive_fn { |
| int& _current; |
| consecutive_fn(int& start) : _current(start) {} |
| int operator()() { return _current++; } |
| }; |
| rgb8_pixel_t p; |
| int start=0; |
| static_generate(p, consecutive_fn(start)); |
| assert(p == rgb8_pixel_t(0,1,2)); |
| \endcode |
| |
| \{ |
| */ |
| |
| template <typename P1,typename Op> |
| GIL_FORCEINLINE |
| void static_generate(P1& dst,Op op) { detail::element_recursion<size<P1>::value>::static_generate(dst,op); } |
| /// \} |
| |
| /** |
| \defgroup ColorBaseAlgorithmTransform static_transform |
| \ingroup ColorBaseAlgorithm |
| \brief Equivalent to std::transform. Pairs the elements semantically |
| |
| Example: Write a generic function that adds two pixels into a homogeneous result pixel. |
| \code |
| template <typename Result> |
| struct my_plus { |
| template <typename T1, typename T2> |
| Result operator()(T1 f1, T2 f2) const { return f1+f2; } |
| }; |
| |
| template <typename Pixel1, typename Pixel2, typename Pixel3> |
| void sum_channels(const Pixel1& p1, const Pixel2& p2, Pixel3& result) { |
| typedef typename channel_type<Pixel3>::type result_channel_t; |
| static_transform(p1,p2,result,my_plus<result_channel_t>()); |
| } |
| |
| rgb8_pixel_t p1(1,2,3); |
| bgr8_pixel_t p2(3,2,1); |
| rgb8_pixel_t result; |
| sum_channels(p1,p2,result); |
| assert(result == rgb8_pixel_t(2,4,6)); |
| \endcode |
| \{ |
| */ |
| |
| //static_transform with one source |
| template <typename Src,typename Dst,typename Op> |
| GIL_FORCEINLINE |
| Op static_transform(Src& src,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); } |
| template <typename Src,typename Dst,typename Op> |
| GIL_FORCEINLINE |
| Op static_transform(const Src& src,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); } |
| //static_transform with two sources |
| template <typename P2,typename P3,typename Dst,typename Op> |
| GIL_FORCEINLINE |
| Op static_transform(P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); } |
| template <typename P2,typename P3,typename Dst,typename Op> |
| GIL_FORCEINLINE |
| Op static_transform(P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); } |
| template <typename P2,typename P3,typename Dst,typename Op> |
| GIL_FORCEINLINE |
| Op static_transform(const P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); } |
| template <typename P2,typename P3,typename Dst,typename Op> |
| GIL_FORCEINLINE |
| Op static_transform(const P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); } |
| /// \} |
| |
| /** |
| \defgroup ColorBaseAlgorithmForEach static_for_each |
| \ingroup ColorBaseAlgorithm |
| \brief Equivalent to std::for_each. Pairs the elements semantically |
| |
| Example: Use static_for_each to increment a planar pixel iterator |
| \code |
| struct increment { |
| template <typename Incrementable> |
| void operator()(Incrementable& x) const { ++x; } |
| }; |
| |
| template <typename ColorBase> |
| void increment_elements(ColorBase& cb) { |
| static_for_each(cb, increment()); |
| } |
| |
| bits8 red[2], green[2], blue[2]; |
| rgb8c_planar_ptr_t p1(red,green,blue); |
| rgb8c_planar_ptr_t p2=p1; |
| increment_elements(p1); |
| ++p2; |
| assert(p1 == p2); |
| \endcode |
| \{ |
| */ |
| |
| //static_for_each with one source |
| template <typename P1,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each( P1& p1, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); } |
| template <typename P1,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(const P1& p1, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); } |
| //static_for_each with two sources |
| template <typename P1,typename P2,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); } |
| template <typename P1,typename P2,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(P1& p1,const P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); } |
| template <typename P1,typename P2,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(const P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); } |
| template <typename P1,typename P2,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(const P1& p1,const P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); } |
| //static_for_each with three sources |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(const P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(const P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(const P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| template <typename P1,typename P2,typename P3,typename Op> |
| GIL_FORCEINLINE |
| Op static_for_each(const P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); } |
| ///\} |
| |
| } } // namespace boost::gil |
| |
| #endif |