/* Copyright 2005-2007 Adobe Systems Incorporated Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /*************************************************************************************************/ #ifndef GIL_SAMPLER_HPP #define GIL_SAMPLER_HPP #include #include "pixel_numeric_operations.hpp" //////////////////////////////////////////////////////////////////////////////////////// /// \file /// \brief Nearest-neighbor and bilinear image samplers. /// NOTE: The code is for example use only. It is not optimized for performance /// \author Lubomir Bourdev and Hailin Jin \n /// Adobe Systems Incorporated /// \date 2005-2007 \n October 30, 2006 /// //////////////////////////////////////////////////////////////////////////////////////// namespace boost { namespace gil { /////////////////////////////////////////////////////////////////////////// //// //// resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view //// /////////////////////////////////////////////////////////////////////////// /* template concept SamplerConcept { template // Models PointNDConcept, where S_COORDS::num_dimensions == SrcView::num_dimensions bool sample(const Sampler& s, const SrcView& src, const S_COORDS& p, DstP result); }; */ /// \brief A sampler that sets the destination pixel to the closest one in the source. If outside the bounds, it doesn't change the destination /// \ingroup ImageAlgorithms struct nearest_neighbor_sampler {}; template bool sample(nearest_neighbor_sampler, const SrcView& src, const point2& p, DstP& result) { point2 center(iround(p)); if (center.x>=0 && center.y>=0 && center.x void cast_pixel(const SrcPixel& src, DstPixel& dst) { static_for_each(src,dst,channel_assigns_t::type, typename channel_type::type>()); } namespace detail { template struct add_dst_mul_src_channel { Weight _w; add_dst_mul_src_channel(Weight w) : _w(w) {} template void operator()(const SrcChannel& src, DstChannel& dst) const { dst += DstChannel(src*_w); } }; // dst += DST_TYPE(src * w) template struct add_dst_mul_src { void operator()(const SrcP& src, Weight weight, DstP& dst) const { static_for_each(src,dst, add_dst_mul_src_channel(weight)); // pixel_assigns_t()( // pixel_plus_t()( // pixel_multiplies_scalar_t()(src,weight), // dst), // dst); } }; } // namespace detail /// \brief A sampler that sets the destination pixel as the bilinear interpolation of the four closest pixels from the source. /// If outside the bounds, it doesn't change the destination /// \ingroup ImageAlgorithms struct bilinear_sampler {}; template bool sample(bilinear_sampler, const SrcView& src, const point2& p, DstP& result) { typedef typename SrcView::value_type SrcP; point2 p0(ifloor(p)); // the closest integer coordinate top left from p point2 frac(p.x-p0.x, p.y-p0.y); if (p0.x < 0 || p0.y < 0 || p0.x>=src.width() || p0.y>=src.height()) return false; pixel::value> > mp(0); // suboptimal typename SrcView::xy_locator loc=src.xy_at(p0.x,p0.y); if (p0.x+1::value> > >()(*loc, (1-frac.x)*(1-frac.y),mp); detail::add_dst_mul_src::value> > >()(loc.x()[1], frac.x *(1-frac.y),mp); ++loc.y(); detail::add_dst_mul_src::value> > >()(*loc, (1-frac.x)* frac.y ,mp); detail::add_dst_mul_src::value> > >()(loc.x()[1], frac.x * frac.y ,mp); } else { // on the last row, but not the bottom-right corner pixel detail::add_dst_mul_src::value> > >()(*loc, (1-frac.x),mp); detail::add_dst_mul_src::value> > >()(loc.x()[1], frac.x ,mp); } } else { if (p0.y+1::value> > >()(*loc, (1-frac.y),mp); ++loc.y(); detail::add_dst_mul_src::value> > >()(*loc, frac.y ,mp); } else { // the bottom-right corner pixel detail::add_dst_mul_src::value> > >()(*loc,1,mp); } } // pixel_assigns_t::value> >,DstP&>()(mp,result); cast_pixel(mp,result); return true; } } } // namespace boost::gil #endif