sampler.hpp 7.6 KB

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