update boost
This commit is contained in:
@@ -89,6 +89,85 @@ point<F> transform(matrix3x2<F> const& mat, point<F2> const& src)
|
||||
return src * mat;
|
||||
}
|
||||
|
||||
/// Returns the inverse of the given affine transformation matrix
|
||||
///
|
||||
/// \warning Floating point arithmetic, use Boost.Rational if precision maters
|
||||
template <typename T>
|
||||
boost::gil::matrix3x2<T> inverse(boost::gil::matrix3x2<T> m)
|
||||
{
|
||||
T const determinant = m.a * m.d - m.b * m.c;
|
||||
|
||||
boost::gil::matrix3x2<T> res;
|
||||
res.a = m.d / determinant;
|
||||
res.b = -m.b / determinant;
|
||||
res.c = -m.c / determinant;
|
||||
res.d = m.a / determinant;
|
||||
res.e = (m.c * m.f - m.d * m.e) / determinant;
|
||||
res.f = (m.b * m.e - m.a * m.f) / determinant;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \fn gil::matrix3x2 center_rotate
|
||||
/// \tparam T Data type for source image dimensions
|
||||
/// \tparam F Data type for angle through which image is to be rotated
|
||||
/// @param dims dimensions of source image
|
||||
/// @param rads angle through which image is to be rotated
|
||||
/// @return A transformation matrix for rotating the source image about its center
|
||||
/// \brief rotates an image from its center point
|
||||
/// using consecutive affine transformations.
|
||||
template<typename T, typename F>
|
||||
boost::gil::matrix3x2<F> center_rotate(boost::gil::point<T> dims,F rads)
|
||||
{
|
||||
const F PI = F(3.141592653589793238);
|
||||
const F c_theta = std::abs(std::cos(rads));
|
||||
const F s_theta = std::abs(std::sin(rads));
|
||||
|
||||
// Bound checks for angle rads
|
||||
while(rads + PI < 0)
|
||||
{
|
||||
rads = rads + PI;
|
||||
}
|
||||
|
||||
while(rads > PI)
|
||||
{
|
||||
rads = rads - PI;
|
||||
}
|
||||
|
||||
// Basic Rotation Matrix
|
||||
boost::gil::matrix3x2<F> rotate = boost::gil::matrix3x2<F>::get_rotate(rads);
|
||||
|
||||
// Find distance for translating the image into view
|
||||
boost::gil::matrix3x2<F> translation(0,0,0,0,0,0);
|
||||
if(rads > 0)
|
||||
{
|
||||
translation.b = s_theta;
|
||||
}
|
||||
else
|
||||
{
|
||||
translation.c = s_theta;
|
||||
}
|
||||
|
||||
if(std::abs(rads) > PI/2)
|
||||
{
|
||||
translation.a = c_theta;
|
||||
translation.d = c_theta;
|
||||
}
|
||||
|
||||
// To bring the complete image into view
|
||||
boost::gil::matrix3x2<F> translate =
|
||||
boost::gil::matrix3x2<F>::get_translate(-1 * dims * translation);
|
||||
|
||||
// To fit inside the source dimensions
|
||||
boost::gil::matrix3x2<F> scale =
|
||||
boost::gil::matrix3x2<F>::get_scale(
|
||||
s_theta * dims.y / dims.x + c_theta ,
|
||||
s_theta * dims.x / dims.y + c_theta
|
||||
);
|
||||
|
||||
return scale * translate * rotate;
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2019-2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,142 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/gil/metafunctions.hpp>
|
||||
#include <boost/gil/pixel_iterator.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \brief Returns the reference proxy associated with a type that has a \p "reference" member type alias.
|
||||
///
|
||||
/// The reference proxy is the reference type, but with stripped-out C++ reference. It models PixelConcept
|
||||
template <typename T>
|
||||
struct pixel_proxy : public remove_reference<typename T::reference> {};
|
||||
|
||||
/// \brief std::for_each for a pair of iterators
|
||||
template <typename Iterator1,typename Iterator2,typename BinaryFunction>
|
||||
BinaryFunction for_each(Iterator1 first1,Iterator1 last1,Iterator2 first2,BinaryFunction f) {
|
||||
while(first1!=last1)
|
||||
f(*first1++,*first2++);
|
||||
return f;
|
||||
}
|
||||
|
||||
template <typename SrcIterator,typename DstIterator>
|
||||
inline DstIterator assign_pixels(SrcIterator src,SrcIterator src_end,DstIterator dst) {
|
||||
for_each(src,src_end,dst,pixel_assigns_t<typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
|
||||
typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type>());
|
||||
return dst+(src_end-src);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <std::size_t Size>
|
||||
struct inner_product_k_t {
|
||||
template <class _InputIterator1, class _InputIterator2, class _Tp,
|
||||
class _BinaryOperation1, class _BinaryOperation2>
|
||||
static _Tp apply(_InputIterator1 __first1,
|
||||
_InputIterator2 __first2, _Tp __init,
|
||||
_BinaryOperation1 __binary_op1,
|
||||
_BinaryOperation2 __binary_op2) {
|
||||
__init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
|
||||
return inner_product_k_t<Size-1>::template apply(__first1+1,__first2+1,__init,
|
||||
__binary_op1, __binary_op2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct inner_product_k_t<0> {
|
||||
template <class _InputIterator1, class _InputIterator2, class _Tp,
|
||||
class _BinaryOperation1, class _BinaryOperation2>
|
||||
static _Tp apply(_InputIterator1 __first1,
|
||||
_InputIterator2 __first2, _Tp __init,
|
||||
_BinaryOperation1 __binary_op1,
|
||||
_BinaryOperation2 __binary_op2) {
|
||||
return __init;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// static version of std::inner_product
|
||||
template <std::size_t Size,
|
||||
class _InputIterator1, class _InputIterator2, class _Tp,
|
||||
class _BinaryOperation1, class _BinaryOperation2>
|
||||
BOOST_FORCEINLINE
|
||||
_Tp inner_product_k(_InputIterator1 __first1,
|
||||
_InputIterator2 __first2,
|
||||
_Tp __init,
|
||||
_BinaryOperation1 __binary_op1,
|
||||
_BinaryOperation2 __binary_op2) {
|
||||
return detail::inner_product_k_t<Size>::template apply(__first1,__first2,__init,
|
||||
__binary_op1, __binary_op2);
|
||||
}
|
||||
|
||||
/// \brief 1D un-guarded correlation with a variable-size kernel
|
||||
template <typename PixelAccum,typename SrcIterator,typename KernelIterator,typename Integer,typename DstIterator>
|
||||
inline DstIterator correlate_pixels_n(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,Integer ker_size,
|
||||
DstIterator dst_begin) {
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
|
||||
using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
|
||||
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
|
||||
while(src_begin!=src_end) {
|
||||
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
|
||||
std::inner_product(src_begin,src_begin+ker_size,ker_begin,acc_zero,
|
||||
pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
|
||||
pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
|
||||
*dst_begin);
|
||||
++src_begin; ++dst_begin;
|
||||
}
|
||||
return dst_begin;
|
||||
}
|
||||
|
||||
/// \brief 1D un-guarded correlation with a fixed-size kernel
|
||||
template <std::size_t Size,typename PixelAccum,typename SrcIterator,typename KernelIterator,typename DstIterator>
|
||||
inline DstIterator correlate_pixels_k(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,
|
||||
DstIterator dst_begin) {
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
|
||||
using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
|
||||
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
|
||||
while(src_begin!=src_end) {
|
||||
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
|
||||
inner_product_k<Size>(src_begin,ker_begin,acc_zero,
|
||||
pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
|
||||
pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
|
||||
*dst_begin);
|
||||
++src_begin; ++dst_begin;
|
||||
}
|
||||
return dst_begin;
|
||||
}
|
||||
|
||||
/// \brief destination is set to be product of the source and a scalar
|
||||
template <typename PixelAccum,typename SrcView,typename Scalar,typename DstView>
|
||||
inline void view_multiplies_scalar(const SrcView& src,const Scalar& scalar,const DstView& dst) {
|
||||
BOOST_ASSERT(src.dimensions() == dst.dimensions());
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename SrcView::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename DstView::value_type>::type;
|
||||
int height=src.height();
|
||||
for(int rr=0;rr<height;++rr) {
|
||||
typename SrcView::x_iterator it_src=src.row_begin(rr);
|
||||
typename DstView::x_iterator it_dst=dst.row_begin(rr);
|
||||
typename SrcView::x_iterator it_src_end=src.row_end(rr);
|
||||
while(it_src!=it_src_end) {
|
||||
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
|
||||
pixel_multiplies_scalar_t<PIXEL_SRC_REF,Scalar,PixelAccum>()(*it_src,scalar),
|
||||
*it_dst);
|
||||
++it_src; ++it_dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/algorithm.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,140 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// Structures for channel-wise numeric operations
|
||||
// Currently defined structures:
|
||||
// channel_plus_t (+), channel_minus_t (-),
|
||||
// channel_multiplies_t (*), channel_divides_t (/),
|
||||
// channel_plus_scalar_t (+s), channel_minus_scalar_t (-s),
|
||||
// channel_multiplies_scalar_t (*s), channel_divides_scalar_t (/s),
|
||||
// channel_halves_t (/=2), channel_zeros_t (=0), channel_assigns_t (=)
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for adding one channel to another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_plus_t {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)+ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for subtracting one channel from another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_minus_t {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)-ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for multiplying one channel to another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_multiplies_t {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)*ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for dividing channels
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_divides_t {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)/ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for adding a scalar to a channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_plus_scalar_t {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch)+ChannelR(s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for subtracting a scalar from a channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_minus_scalar_t {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch-s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for multiplying a scalar to one channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_multiplies_scalar_t {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch)*ChannelR(s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for dividing a channel by a scalar
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_divides_scalar_t {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch)/ChannelR(s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for halving a channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel>
|
||||
struct channel_halves_t {
|
||||
typename channel_traits<Channel>::reference
|
||||
operator()(typename channel_traits<Channel>::reference ch) const {
|
||||
return ch/=2.0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for setting a channel to zero
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel>
|
||||
struct channel_zeros_t {
|
||||
typename channel_traits<Channel>::reference
|
||||
operator()(typename channel_traits<Channel>::reference ch) const {
|
||||
return ch=Channel(0);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for assigning one channel to another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2>
|
||||
struct channel_assigns_t {
|
||||
typename channel_traits<Channel2>::reference
|
||||
operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::reference ch2) const {
|
||||
return ch2=Channel2(ch1);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::gil
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/channel_numeric_operations.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2019 Miral Shah <miralshah2211@gmail.com>
|
||||
// Copyright 2019-2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,210 +10,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/algorithm.hpp>
|
||||
#include <boost/gil/extension/numeric/kernel.hpp>
|
||||
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/gil/algorithm.hpp>
|
||||
#include <boost/gil/image_view_factory.hpp>
|
||||
#include <boost/gil/metafunctions.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// 2D seperable convolutions and correlations
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
/// Boundary options for 1D correlations/convolutions
|
||||
enum convolve_boundary_option {
|
||||
convolve_option_output_ignore, /// do nothing to the output
|
||||
convolve_option_output_zero, /// set the output to zero
|
||||
convolve_option_extend_padded, /// assume the source boundaries to be padded already
|
||||
convolve_option_extend_zero, /// assume the source boundaries to be zero
|
||||
convolve_option_extend_constant /// assume the source boundaries to be the boundary value
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
/// compute the correlation of 1D kernel with the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView,typename Correlator>
|
||||
void correlate_rows_imp(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option,
|
||||
Correlator correlator) {
|
||||
BOOST_ASSERT(src.dimensions() == dst.dimensions());
|
||||
BOOST_ASSERT(ker.size() != 0);
|
||||
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename SrcView::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename DstView::value_type>::type;
|
||||
|
||||
if(ker.size()==1) {//reduces to a multiplication
|
||||
view_multiplies_scalar<PixelAccum>(src,*ker.begin(),dst);
|
||||
return;
|
||||
}
|
||||
|
||||
int width=src.width(),height=src.height();
|
||||
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
|
||||
if (width==0) return;
|
||||
if (option==convolve_option_output_ignore || option==convolve_option_output_zero) {
|
||||
typename DstView::value_type dst_zero; pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(acc_zero,dst_zero);
|
||||
if (width<(int)ker.size()) {
|
||||
if (option==convolve_option_output_zero)
|
||||
fill_pixels(dst,dst_zero);
|
||||
} else {
|
||||
std::vector<PixelAccum> buffer(width);
|
||||
for(int rr=0;rr<height;++rr) {
|
||||
assign_pixels(src.row_begin(rr),src.row_end(rr),&buffer.front());
|
||||
typename DstView::x_iterator it_dst=dst.row_begin(rr);
|
||||
if (option==convolve_option_output_zero)
|
||||
std::fill_n(it_dst,ker.left_size(),dst_zero);
|
||||
it_dst+=ker.left_size();
|
||||
correlator(&buffer.front(),&buffer.front()+width+1-ker.size(),
|
||||
ker.begin(),it_dst);
|
||||
it_dst+=width+1-ker.size();
|
||||
if (option==convolve_option_output_zero)
|
||||
std::fill_n(it_dst,ker.right_size(),dst_zero);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::vector<PixelAccum> buffer(width+ker.size()-1);
|
||||
for(int rr=0;rr<height;++rr) {
|
||||
PixelAccum* it_buffer=&buffer.front();
|
||||
if (option==convolve_option_extend_padded) {
|
||||
assign_pixels(src.row_begin(rr)-ker.left_size(),
|
||||
src.row_end(rr)+ker.right_size(),
|
||||
it_buffer);
|
||||
} else if (option==convolve_option_extend_zero) {
|
||||
std::fill_n(it_buffer,ker.left_size(),acc_zero);
|
||||
it_buffer+=ker.left_size();
|
||||
assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
|
||||
it_buffer+=width;
|
||||
std::fill_n(it_buffer,ker.right_size(),acc_zero);
|
||||
} else if (option==convolve_option_extend_constant) {
|
||||
PixelAccum filler;
|
||||
pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(*src.row_begin(rr),filler);
|
||||
std::fill_n(it_buffer,ker.left_size(),filler);
|
||||
it_buffer+=ker.left_size();
|
||||
assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
|
||||
it_buffer+=width;
|
||||
pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(src.row_end(rr)[-1],filler);
|
||||
std::fill_n(it_buffer,ker.right_size(),filler);
|
||||
}
|
||||
correlator(&buffer.front(),&buffer.front()+width,
|
||||
ker.begin(),
|
||||
dst.row_begin(rr));
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename PixelAccum>
|
||||
class correlator_n {
|
||||
private:
|
||||
std::size_t _size;
|
||||
public:
|
||||
correlator_n(std::size_t size_in) : _size(size_in) {}
|
||||
template <typename SrcIterator,typename KernelIterator,typename DstIterator>
|
||||
void operator()(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,
|
||||
DstIterator dst_begin) {
|
||||
correlate_pixels_n<PixelAccum>(src_begin,src_end,ker_begin,_size,dst_begin);
|
||||
}
|
||||
};
|
||||
template <std::size_t Size,typename PixelAccum>
|
||||
struct correlator_k {
|
||||
public:
|
||||
template <typename SrcIterator,typename KernelIterator,typename DstIterator>
|
||||
void operator()(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,
|
||||
DstIterator dst_begin){
|
||||
correlate_pixels_k<Size,PixelAccum>(src_begin,src_end,ker_begin,dst_begin);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D variable-size kernel along the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void correlate_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_n<PixelAccum>(ker.size()));
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D variable-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void correlate_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D variable-size kernel along the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void convolve_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows<PixelAccum>(src,reverse_kernel(ker),dst,option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D variable-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void convolve_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
convolve_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D fixed-size kernel along the rows of an image
|
||||
template <typename PixelAccum, typename SrcView, typename Kernel, typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void correlate_rows_fixed(const SrcView& src, const Kernel& kernel, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero)
|
||||
{
|
||||
using correlator = detail::correlator_k
|
||||
<
|
||||
std::extent<Kernel>::value,
|
||||
PixelAccum
|
||||
>;
|
||||
detail::correlate_rows_imp<PixelAccum>(
|
||||
src, kernel, dst, option, correlator{});
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D fixed-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void correlate_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D fixed-size kernel along the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void convolve_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows_fixed<PixelAccum>(src,reverse_kernel(ker),dst,option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D fixed-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
BOOST_FORCEINLINE
|
||||
void convolve_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
convolve_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/image_processing/convolve.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,118 +1,18 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2019 Miral Shah <miralshah2211@gmail.com>
|
||||
// Copyright 2022 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
|
||||
|
||||
#include <boost/gil/utilities.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// Definitions of 1D fixed-size and variable-size kernels and related operations
|
||||
|
||||
namespace detail {
|
||||
|
||||
/// \brief kernel adaptor for one-dimensional cores
|
||||
/// Core needs to provide size(),begin(),end(),operator[],
|
||||
/// value_type,iterator,const_iterator,reference,const_reference
|
||||
template <typename Core>
|
||||
class kernel_1d_adaptor : public Core {
|
||||
private:
|
||||
std::size_t _center;
|
||||
public:
|
||||
kernel_1d_adaptor() : _center(0) {}
|
||||
|
||||
explicit kernel_1d_adaptor(std::size_t center_in)
|
||||
: _center(center_in)
|
||||
{
|
||||
BOOST_ASSERT(_center < this->size());
|
||||
}
|
||||
|
||||
kernel_1d_adaptor(std::size_t size_in, std::size_t center_in)
|
||||
: Core(size_in)
|
||||
, _center(center_in)
|
||||
{
|
||||
BOOST_ASSERT(_center < this->size());
|
||||
}
|
||||
|
||||
kernel_1d_adaptor(kernel_1d_adaptor const& k_in) : Core(k_in), _center(k_in._center) {}
|
||||
|
||||
kernel_1d_adaptor& operator=(const kernel_1d_adaptor& k_in) {
|
||||
Core::operator=(k_in);
|
||||
_center=k_in._center;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::size_t left_size() const
|
||||
{
|
||||
BOOST_ASSERT(_center < this->size());
|
||||
return _center;
|
||||
}
|
||||
|
||||
std::size_t right_size() const
|
||||
{
|
||||
BOOST_ASSERT(_center < this->size());
|
||||
return this->size() - _center - 1;
|
||||
}
|
||||
|
||||
std::size_t& center() {return _center;}
|
||||
const std::size_t& center() const {return _center;}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief variable-size kernel
|
||||
template <typename T, typename Alloc = std::allocator<T> >
|
||||
class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T,Alloc>>
|
||||
{
|
||||
using parent_t = detail::kernel_1d_adaptor<std::vector<T,Alloc>>;
|
||||
public:
|
||||
kernel_1d() {}
|
||||
kernel_1d(std::size_t size_in,std::size_t center_in) : parent_t(size_in,center_in) {}
|
||||
template <typename FwdIterator>
|
||||
kernel_1d(FwdIterator elements, std::size_t size_in, std::size_t center_in) : parent_t(size_in,center_in) {
|
||||
detail::copy_n(elements,size_in,this->begin());
|
||||
}
|
||||
kernel_1d(const kernel_1d& k_in) : parent_t(k_in) {}
|
||||
};
|
||||
|
||||
/// \brief static-size kernel
|
||||
template <typename T,std::size_t Size>
|
||||
class kernel_1d_fixed : public detail::kernel_1d_adaptor<std::array<T,Size>>
|
||||
{
|
||||
using parent_t = detail::kernel_1d_adaptor<std::array<T,Size>>;
|
||||
public:
|
||||
kernel_1d_fixed() {}
|
||||
explicit kernel_1d_fixed(std::size_t center_in) : parent_t(center_in) {}
|
||||
|
||||
template <typename FwdIterator>
|
||||
explicit kernel_1d_fixed(FwdIterator elements, std::size_t center_in) : parent_t(center_in) {
|
||||
detail::copy_n(elements,Size,this->begin());
|
||||
}
|
||||
kernel_1d_fixed(const kernel_1d_fixed& k_in) : parent_t(k_in) {}
|
||||
};
|
||||
|
||||
/// \brief reverse a kernel
|
||||
template <typename Kernel>
|
||||
inline Kernel reverse_kernel(const Kernel& kernel) {
|
||||
Kernel result(kernel);
|
||||
result.center()=kernel.right_size();
|
||||
std::reverse(result.begin(), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/image_processing/kernel.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,165 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/gil/color_base_algorithm.hpp>
|
||||
#include <boost/gil/pixel.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// Structures for pixel-wise numeric operations
|
||||
// Currently defined structures:
|
||||
// pixel_plus_t (+), pixel_minus_t (-)
|
||||
// pixel_multiplies_scalar_t (*), pixel_divides_scalar_t (/)
|
||||
// pixel_halves_t (/=2), pixel_zeros_t (=0)
|
||||
// pixel_assigns_t (=)
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for adding two pixels
|
||||
template <typename PixelRef1, // models pixel concept
|
||||
typename PixelRef2, // models pixel concept
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_plus_t {
|
||||
PixelR operator() (const PixelRef1& p1,
|
||||
const PixelRef2& p2) const {
|
||||
PixelR result;
|
||||
static_transform(p1,p2,result,
|
||||
channel_plus_t<typename channel_type<PixelRef1>::type,
|
||||
typename channel_type<PixelRef2>::type,
|
||||
typename channel_type<PixelR>::type>());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for subtracting two pixels
|
||||
template <typename PixelRef1, // models pixel concept
|
||||
typename PixelRef2, // models pixel concept
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_minus_t {
|
||||
PixelR operator() (const PixelRef1& p1,
|
||||
const PixelRef2& p2) const {
|
||||
PixelR result;
|
||||
static_transform(p1,p2,result,
|
||||
channel_minus_t<typename channel_type<PixelRef1>::type,
|
||||
typename channel_type<PixelRef2>::type,
|
||||
typename channel_type<PixelR>::type>());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for multiplying scalar to a pixel
|
||||
template <typename PixelRef, // models pixel concept
|
||||
typename Scalar, // models a scalar type
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_multiplies_scalar_t {
|
||||
PixelR operator () (const PixelRef& p,
|
||||
const Scalar& s) const {
|
||||
PixelR result;
|
||||
static_transform(p,result,
|
||||
std::bind(channel_multiplies_scalar_t<typename channel_type<PixelRef>::type,
|
||||
Scalar,
|
||||
typename channel_type<PixelR>::type>(),
|
||||
std::placeholders::_1, s));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for dividing two pixels
|
||||
template <typename PixelRef1, // models pixel concept
|
||||
typename PixelRef2, // models pixel concept
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_multiply_t {
|
||||
PixelR operator() (const PixelRef1& p1,
|
||||
const PixelRef2& p2) const {
|
||||
PixelR result;
|
||||
static_transform(p1,p2,result,
|
||||
channel_multiplies_t<typename channel_type<PixelRef1>::type,
|
||||
typename channel_type<PixelRef2>::type,
|
||||
typename channel_type<PixelR>::type>());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for dividing a pixel by a scalar
|
||||
template <typename PixelRef, // models pixel concept
|
||||
typename Scalar, // models a scalar type
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_divides_scalar_t {
|
||||
PixelR operator () (const PixelRef& p,
|
||||
const Scalar& s) const {
|
||||
PixelR result;
|
||||
static_transform(p,result,
|
||||
std::bind(channel_divides_scalar_t<typename channel_type<PixelRef>::type,
|
||||
Scalar,
|
||||
typename channel_type<PixelR>::type>(),
|
||||
std::placeholders::_1, s));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for dividing two pixels
|
||||
template <typename PixelRef1, // models pixel concept
|
||||
typename PixelRef2, // models pixel concept
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_divide_t {
|
||||
PixelR operator() (const PixelRef1& p1,
|
||||
const PixelRef2& p2) const {
|
||||
PixelR result;
|
||||
static_transform(p1,p2,result,
|
||||
channel_divides_t<typename channel_type<PixelRef1>::type,
|
||||
typename channel_type<PixelRef2>::type,
|
||||
typename channel_type<PixelR>::type>());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for dividing a pixel by 2
|
||||
template <typename PixelRef> // models pixel concept
|
||||
struct pixel_halves_t {
|
||||
PixelRef& operator () (PixelRef& p) const {
|
||||
static_for_each(p,channel_halves_t<typename channel_type<PixelRef>::type>());
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for setting a pixel to zero (for whatever zero means)
|
||||
template <typename PixelRef> // models pixel concept
|
||||
struct pixel_zeros_t {
|
||||
PixelRef& operator () (PixelRef& p) const {
|
||||
static_for_each(p,channel_zeros_t<typename channel_type<PixelRef>::type>());
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
// Hailin: This is how you can do it:
|
||||
template <typename Pixel>
|
||||
void zero_channels(Pixel& p) {
|
||||
static_for_each(p,channel_zeros_t<typename channel_type<Pixel>::type>());
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
///definition and a generic implementation for casting and assigning a pixel to another
|
||||
///user should specialize it for better performance
|
||||
template <typename PixelRef, // models pixel concept
|
||||
typename PixelRefR> // models pixel concept
|
||||
struct pixel_assigns_t {
|
||||
PixelRefR operator () (const PixelRef& src,
|
||||
PixelRefR& dst) const {
|
||||
static_for_each(src,dst,channel_assigns_t<typename channel_type<PixelRef>::type,
|
||||
typename channel_type<PixelRefR>::type>());
|
||||
return dst;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::gil
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/pixel_numeric_operations.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -70,34 +70,34 @@ namespace detail {
|
||||
/// \brief resample_pixels when the source is run-time specified
|
||||
/// If invoked on incompatible views, throws std::bad_cast()
|
||||
/// \ingroup ImageAlgorithms
|
||||
template <typename Sampler, typename Types1, typename V2, typename MapFn>
|
||||
void resample_pixels(const any_image_view<Types1>& src, const V2& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
|
||||
template <typename Sampler, typename ...Types1, typename V2, typename MapFn>
|
||||
void resample_pixels(const any_image_view<Types1...>& src, const V2& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
|
||||
{
|
||||
apply_operation(src, std::bind(
|
||||
variant2::visit(std::bind(
|
||||
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
|
||||
std::placeholders::_1,
|
||||
dst));
|
||||
dst), src);
|
||||
}
|
||||
|
||||
/// \brief resample_pixels when the destination is run-time specified
|
||||
/// If invoked on incompatible views, throws std::bad_cast()
|
||||
/// \ingroup ImageAlgorithms
|
||||
template <typename Sampler, typename V1, typename Types2, typename MapFn>
|
||||
void resample_pixels(const V1& src, const any_image_view<Types2>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
|
||||
template <typename Sampler, typename V1, typename ...Types2, typename MapFn>
|
||||
void resample_pixels(const V1& src, const any_image_view<Types2...>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
apply_operation(dst, std::bind(
|
||||
variant2::visit(std::bind(
|
||||
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
|
||||
src,
|
||||
std::placeholders::_1));
|
||||
std::placeholders::_1), dst);
|
||||
}
|
||||
|
||||
/// \brief resample_pixels when both the source and the destination are run-time specified
|
||||
/// If invoked on incompatible views, throws std::bad_cast()
|
||||
/// \ingroup ImageAlgorithms
|
||||
template <typename Sampler, typename SrcTypes, typename DstTypes, typename MapFn>
|
||||
void resample_pixels(const any_image_view<SrcTypes>& src, const any_image_view<DstTypes>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
|
||||
apply_operation(src,dst,detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler));
|
||||
template <typename Sampler, typename ...SrcTypes, typename ...DstTypes, typename MapFn>
|
||||
void resample_pixels(const any_image_view<SrcTypes...>& src, const any_image_view<DstTypes...>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
|
||||
variant2::visit(detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler), src, dst);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,8 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
|
||||
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
|
||||
#include <boost/gil/pixel_numeric_operations.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
@@ -180,7 +181,6 @@ bool sample(bilinear_sampler, SrcView const& src, point<F> const& p, DstP& resul
|
||||
cast_pixel(mp,src_result);
|
||||
|
||||
color_convert(src_result, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user