]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/gil/extension/numeric/sampler.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / gil / extension / numeric / sampler.hpp
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>
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>
52 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>
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;
68 add_dst_mul_src_channel(Weight w) : _w(w) {}
69
70 template <typename SrcChannel, typename DstChannel>
71 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 {
79 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>
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