Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:00

0001 //
0002 // Copyright 2005-2007 Adobe Systems Incorporated
0003 // Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
0004 //
0005 // Distributed under the Boost Software License, Version 1.0
0006 // See accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt
0008 //
0009 #ifndef BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
0010 #define BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
0011 
0012 #include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
0013 #include <boost/gil/pixel_numeric_operations.hpp>
0014 
0015 namespace boost { namespace gil {
0016 
0017 // Nearest-neighbor and bilinear image samplers.
0018 // NOTE: The code is for example use only. It is not optimized for performance
0019 
0020 ///////////////////////////////////////////////////////////////////////////
0021 ////
0022 ////     resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
0023 ////
0024 ///////////////////////////////////////////////////////////////////////////
0025 /*
0026 template <typename Sampler>
0027 concept SamplerConcept {
0028     template <typename DstP,      // Models PixelConcept
0029               typename SrcView,    // Models RandomAccessNDImageViewConcept
0030               typename S_COORDS>  // Models PointNDConcept, where S_COORDS::num_dimensions == SrcView::num_dimensions
0031     bool sample(const Sampler& s, const SrcView& src, const S_COORDS& p, DstP result);
0032 };
0033 */
0034 
0035 /// \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
0036 /// \ingroup ImageAlgorithms
0037 struct nearest_neighbor_sampler {};
0038 
0039 template <typename DstP, typename SrcView, typename F>
0040 bool sample(nearest_neighbor_sampler, SrcView const& src, point<F> const& p, DstP& result)
0041 {
0042     typename SrcView::point_t center(iround(p));
0043     if (center.x >= 0 && center.y >= 0 && center.x < src.width() && center.y < src.height())
0044     {
0045         result=src(center.x,center.y);
0046         return true;
0047     }
0048     return false;
0049 }
0050 
0051 struct cast_channel_fn {
0052     template <typename SrcChannel, typename DstChannel>
0053     void operator()(const SrcChannel& src, DstChannel& dst) {
0054         using dst_value_t = typename channel_traits<DstChannel>::value_type;
0055         dst = dst_value_t(src);
0056     }
0057 };
0058 
0059 template <typename SrcPixel, typename DstPixel>
0060 void cast_pixel(const SrcPixel& src, DstPixel& dst) {
0061     static_for_each(src,dst,cast_channel_fn());
0062 }
0063 
0064 namespace detail {
0065 
0066 template <typename Weight>
0067 struct add_dst_mul_src_channel {
0068     Weight _w;
0069     add_dst_mul_src_channel(Weight w) : _w(w) {}
0070 
0071     template <typename SrcChannel, typename DstChannel>
0072     void operator()(const SrcChannel& src, DstChannel& dst) const {
0073         dst += DstChannel(src*_w);
0074     }
0075 };
0076 
0077 // dst += DST_TYPE(src * w)
0078 template <typename SrcP,typename Weight,typename DstP>
0079 struct add_dst_mul_src {
0080     void operator()(const SrcP& src, Weight weight, DstP& dst) const {
0081         static_for_each(src,dst, add_dst_mul_src_channel<Weight>(weight));
0082 //        pixel_assigns_t<DstP,DstP&>()(
0083 //            pixel_plus_t<DstP,DstP,DstP>()(
0084 //                pixel_multiplies_scalar_t<SrcP,Weight,DstP>()(src,weight),
0085 //                dst),
0086 //            dst);
0087     }
0088 };
0089 } // namespace detail
0090 
0091 /// \brief A sampler that sets the destination pixel as the bilinear interpolation of the four closest pixels from the source.
0092 /// If outside the bounds, it doesn't change the destination
0093 /// \ingroup ImageAlgorithms
0094 struct bilinear_sampler {};
0095 
0096 template <typename DstP, typename SrcView, typename F>
0097 bool sample(bilinear_sampler, SrcView const& src, point<F> const& p, DstP& result)
0098 {
0099     using SrcP = typename SrcView::value_type;
0100     point_t p0(ifloor(p.x), ifloor(p.y)); // the closest integer coordinate top left from p
0101     point<F> frac(p.x-p0.x, p.y-p0.y);
0102 
0103     if (p0.x < -1 || p0.y < -1 || p0.x>=src.width() || p0.y>=src.height())
0104     {
0105         return false;
0106     }
0107 
0108     pixel<F,devicen_layout_t<num_channels<SrcView>::value> > mp(0); // suboptimal
0109     typename SrcView::xy_locator loc=src.xy_at(p0.x,p0.y);
0110 
0111     if (p0.x == -1)
0112     {
0113         if (p0.y == -1)
0114         {
0115             // the top-left corner pixel
0116             ++loc.y();
0117             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],  1        ,mp);
0118         }
0119         else if (p0.y+1<src.height())
0120         {
0121             // on the first column, but not the top-left nor bottom-left corner pixel
0122             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], (1-frac.y),mp);
0123             ++loc.y();
0124             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],    frac.y ,mp);
0125         }
0126         else
0127         {
0128             // the bottom-left corner pixel
0129             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],  1        ,mp);
0130         }
0131     }
0132     else if (p0.x+1<src.width())
0133     {
0134         if (p0.y == -1)
0135         {
0136             // on the first row, but not the top-left nor top-right corner pixel
0137             ++loc.y();
0138             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)           ,mp);
0139             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],   frac.x            ,mp);
0140         }
0141         else if (p0.y+1<src.height())
0142         {
0143             // most common case - inside the image, not on the frist nor last row/column
0144             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)*(1-frac.y),mp);
0145             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);
0146             ++loc.y();
0147             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)*   frac.y ,mp);
0148             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],   frac.x *   frac.y ,mp);
0149         }
0150         else
0151         {
0152             // on the last row, but not the bottom-left nor bottom-right corner pixel
0153             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,      (1-frac.x)           ,mp);
0154             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1],   frac.x            ,mp);
0155         }
0156     }
0157     else
0158     {
0159         if (p0.y == -1)
0160         {
0161             // the top-right corner pixel
0162             ++loc.y();
0163             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,  1        ,mp);
0164         }
0165         else if (p0.y+1<src.height())
0166         {
0167             // on the last column, but not the top-right nor bottom-right corner pixel
0168             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.y),mp);
0169             ++loc.y();
0170             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,    frac.y ,mp);
0171         }
0172         else
0173         {
0174             // the bottom-right corner pixel
0175             detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,  1        ,mp);
0176         }
0177     }
0178 
0179     // Convert from floating point average value to the source type
0180     SrcP src_result;
0181     cast_pixel(mp,src_result);
0182 
0183     color_convert(src_result, result);
0184     return true;
0185 }
0186 
0187 }}  // namespace boost::gil
0188 
0189 #endif