• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
9 #define BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
10 
11 #include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
12 #include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
13 
14 namespace boost { namespace gil {
15 
16 // Nearest-neighbor and bilinear image samplers.
17 // NOTE: The code is for example use only. It is not optimized for performance
18 
19 ///////////////////////////////////////////////////////////////////////////
20 ////
21 ////     resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
22 ////
23 ///////////////////////////////////////////////////////////////////////////
24 /*
25 template <typename Sampler>
26 concept SamplerConcept {
27     template <typename DstP,      // Models PixelConcept
28               typename SrcView,    // Models RandomAccessNDImageViewConcept
29               typename S_COORDS>  // Models PointNDConcept, where S_COORDS::num_dimensions == SrcView::num_dimensions
30     bool sample(const Sampler& s, const SrcView& src, const S_COORDS& p, DstP result);
31 };
32 */
33 
34 /// \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
35 /// \ingroup ImageAlgorithms
36 struct nearest_neighbor_sampler {};
37 
38 template <typename DstP, typename SrcView, typename F>
sample(nearest_neighbor_sampler,SrcView const & src,point<F> const & p,DstP & result)39 bool sample(nearest_neighbor_sampler, SrcView const& src, point<F> const& p, DstP& result)
40 {
41     typename SrcView::point_t center(iround(p));
42     if (center.x >= 0 && center.y >= 0 && center.x < src.width() && center.y < src.height())
43     {
44         result=src(center.x,center.y);
45         return true;
46     }
47     return false;
48 }
49 
50 struct cast_channel_fn {
51     template <typename SrcChannel, typename DstChannel>
operator ()boost::gil::cast_channel_fn52     void operator()(const SrcChannel& src, DstChannel& dst) {
53         using dst_value_t = typename channel_traits<DstChannel>::value_type;
54         dst = dst_value_t(src);
55     }
56 };
57 
58 template <typename SrcPixel, typename DstPixel>
cast_pixel(const SrcPixel & src,DstPixel & dst)59 void cast_pixel(const SrcPixel& src, DstPixel& dst) {
60     static_for_each(src,dst,cast_channel_fn());
61 }
62 
63 namespace detail {
64 
65 template <typename Weight>
66 struct add_dst_mul_src_channel {
67     Weight _w;
add_dst_mul_src_channelboost::gil::detail::add_dst_mul_src_channel68     add_dst_mul_src_channel(Weight w) : _w(w) {}
69 
70     template <typename SrcChannel, typename DstChannel>
operator ()boost::gil::detail::add_dst_mul_src_channel71     void operator()(const SrcChannel& src, DstChannel& dst) const {
72         dst += DstChannel(src*_w);
73     }
74 };
75 
76 // dst += DST_TYPE(src * w)
77 template <typename SrcP,typename Weight,typename DstP>
78 struct add_dst_mul_src {
operator ()boost::gil::detail::add_dst_mul_src79     void operator()(const SrcP& src, Weight weight, DstP& dst) const {
80         static_for_each(src,dst, add_dst_mul_src_channel<Weight>(weight));
81 //        pixel_assigns_t<DstP,DstP&>()(
82 //            pixel_plus_t<DstP,DstP,DstP>()(
83 //                pixel_multiplies_scalar_t<SrcP,Weight,DstP>()(src,weight),
84 //                dst),
85 //            dst);
86     }
87 };
88 } // namespace detail
89 
90 /// \brief A sampler that sets the destination pixel as the bilinear interpolation of the four closest pixels from the source.
91 /// If outside the bounds, it doesn't change the destination
92 /// \ingroup ImageAlgorithms
93 struct bilinear_sampler {};
94 
95 template <typename DstP, typename SrcView, typename F>
sample(bilinear_sampler,SrcView const & src,point<F> const & p,DstP & result)96 bool sample(bilinear_sampler, SrcView const& src, point<F> const& p, DstP& result)
97 {
98     using SrcP = typename SrcView::value_type;
99     point_t p0(ifloor(p.x), ifloor(p.y)); // the closest integer coordinate top left from p
100     point<F> frac(p.x-p0.x, p.y-p0.y);
101 
102     if (p0.x < -1 || p0.y < -1 || p0.x>=src.width() || p0.y>=src.height())
103     {
104         return false;
105     }
106 
107 	pixel<F,devicen_layout_t<num_channels<SrcView>::value> > mp(0); // suboptimal
108 	typename SrcView::xy_locator loc=src.xy_at(p0.x,p0.y);
109 
110 	if (p0.x == -1)
111     {
112 		if (p0.y == -1)
113         {
114 		    // the top-left corner pixel
115 			++loc.y();
116 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],  1        ,mp);
117 		}
118         else if (p0.y+1<src.height())
119         {
120             // on the first column, but not the top-left nor bottom-left corner pixel
121 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], (1-frac.y),mp);
122 			++loc.y();
123 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],    frac.y ,mp);
124 		}
125         else
126         {
127 			// the bottom-left corner pixel
128 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],  1        ,mp);
129 		}
130 	}
131     else if (p0.x+1<src.width())
132     {
133 		if (p0.y == -1)
134         {
135 		    // on the first row, but not the top-left nor top-right corner pixel
136 			++loc.y();
137 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)           ,mp);
138 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],   frac.x            ,mp);
139 		}
140         else if (p0.y+1<src.height())
141         {
142 			// most common case - inside the image, not on the frist nor last row/column
143 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)*(1-frac.y),mp);
144 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],   frac.x *(1-frac.y),mp);
145 			++loc.y();
146 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)*   frac.y ,mp);
147 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],   frac.x *   frac.y ,mp);
148 		}
149         else
150         {
151 			// on the last row, but not the bottom-left nor bottom-right corner pixel
152 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)           ,mp);
153 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],   frac.x            ,mp);
154 		}
155 	}
156     else
157     {
158         if (p0.y == -1)
159         {
160             // the top-right corner pixel
161             ++loc.y();
162             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,  1        ,mp);
163         }
164         else if (p0.y+1<src.height())
165         {
166 			// on the last column, but not the top-right nor bottom-right corner pixel
167 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.y),mp);
168 			++loc.y();
169 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,    frac.y ,mp);
170 		}
171         else
172         {
173 			// the bottom-right corner pixel
174 			detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,  1        ,mp);
175 		}
176 	}
177 
178 	// Convert from floating point average value to the source type
179 	SrcP src_result;
180 	cast_pixel(mp,src_result);
181 
182 	color_convert(src_result, result);
183 	return true;
184 }
185 
186 }}  // namespace boost::gil
187 
188 #endif
189