#ifndef GIL_COLOR_MERGE_HPP #define GIL_COLOR_MERGE_HPP //////////////////////////////////////////////////////////////////////////////////////// /// \file /// \brief GIL default color merging /// \author Eloi Du Bois /// \date October 27, 2009 /// /// //////////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include namespace boost { namespace gil { //////////////////////////////////////////////////////////////////////////////////////// /// /// COLOR MERGING /// //////////////////////////////////////////////////////////////////////////////////////// /// @defgroup ColorMerge Color Space Merging /// \brief Functors need to heritates from merge_functor template struct merge_functor { // boost::mpl::true_ or false_ typedef NEED_ALPHA need_alpha_t; }; namespace detail { template struct default_alpha_channel_merging { // View iterators are needed because merging depends on each alpha // channel const ItA& _itA; /// View iterator src A const ItB& _itB; /// View iterator src B default_alpha_channel_merging( const ItA& itA, const ItB& itB ) : _itA( itA ), _itB( itB ) {} template void operator()( const V1& srcA, const V2& srcB, V3& dst ) const { F::merge( get_color(_itA, alpha_t()), get_color(_itB, alpha_t()), srcA, srcB, dst ); } }; template struct default_channel_merging { template void operator()( const V1& srcA, const V2& srcB, V3& dstC ) const { F::merge( srcA, srcB, dstC ); } }; /// Implementation for pixel merging template < class F > struct merge_pixels_alpha_impl { template < typename View1, typename View2, typename View3 > inline void operator()( View1& src1, View2& src2, View3& dst ) { View3 srcA(boost::gil::color_converted_view(src1)); View3 srcB(boost::gil::color_converted_view(src2)); typedef typename View3::value_type channel_t; // Need alpha channel on sources & destination for( std::ptrdiff_t y = 0; y < dst.height(); ++y ) { typename View3::x_iterator srcIt1 = srcA.row_begin( y ); typename View3::x_iterator srcIt2 = srcB.row_begin( y ); typename View3::x_iterator dstIt = dst.row_begin( y ); for( std::ptrdiff_t x = 0; x < dst.width(); ++x ) static_for_each( srcIt1[x], srcIt2[x], dstIt[x], default_alpha_channel_merging < F, channel_t, channel_t >( srcIt1[x], srcIt2[x] ) ); } } }; template < class F > struct merge_pixels_impl { template < typename View1, typename View2, typename View3 > inline void operator()( View1& src1, View2& src2, View3& dst ) { // Need alpha channel on sources & destination for( std::ptrdiff_t y = 0; y < dst.height(); ++y ) { typename View1::x_iterator srcIt1 = src1.row_begin( y ); typename View2::x_iterator srcIt2 = src2.row_begin( y ); typename View3::x_iterator dstIt = dst.row_begin( y ); for( std::ptrdiff_t x = 0; x < dst.width(); ++x ) static_for_each( srcIt1[x], srcIt2[x], dstIt[x], default_channel_merging() ); } } }; } template < class F, typename View1, typename View2, typename View3> void merge_pixels( View1& src1, View2& src2, View3& dst ) { // If merging functor needs alpha, check if destination contains alpha. typedef typename mpl::contains::type, alpha_t>::type has_alpha_t; BOOST_STATIC_ASSERT((has_alpha_t::value == F::need_alpha_t::value) || F::need_alpha_t::value == false); // Chose the right merging function according to alpha channel needs typename mpl::if_< typename F::need_alpha_t, typename detail::merge_pixels_alpha_impl, typename detail::merge_pixels_impl >::type merger; // Apply merger(src1, src2, dst); } } } // namespace boost::gil #endif