add boost on mac

This commit is contained in:
Bassem Girgis
2019-08-10 16:38:17 -05:00
parent 861b918727
commit be945cb63b
14105 changed files with 2714968 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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_AFFINE_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP
#include <boost/gil/point.hpp>
namespace boost { namespace gil {
////////////////////////////////////////////////////////////////////////////////////////
///
/// Simple matrix to do 2D affine transformations. It is actually 3x3 but the last column is [0 0 1]
///
////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
class matrix3x2 {
public:
matrix3x2() : a(1), b(0), c(0), d(1), e(0), f(0) {}
matrix3x2(T A, T B, T C, T D, T E, T F) : a(A),b(B),c(C),d(D),e(E),f(F) {}
matrix3x2(const matrix3x2& mat) : a(mat.a), b(mat.b), c(mat.c), d(mat.d), e(mat.e), f(mat.f) {}
matrix3x2& operator=(const matrix3x2& m) { a=m.a; b=m.b; c=m.c; d=m.d; e=m.e; f=m.f; return *this; }
matrix3x2& operator*=(const matrix3x2& m) { (*this) = (*this)*m; return *this; }
static matrix3x2 get_rotate(T rads) { T c=std::cos(rads); T s=std::sin(rads); return matrix3x2(c,s,-s,c,0,0); }
static matrix3x2 get_translate(point<T> const& t)
{
return matrix3x2(1, 0, 0, 1, t.x, t.y);
}
static matrix3x2 get_translate(T x, T y) { return matrix3x2(1 ,0,0,1 ,x, y ); }
static matrix3x2 get_scale(point<T> const& s)
{
return matrix3x2(s.x, 0, 0, s.y, 0, 0);
}
static matrix3x2 get_scale(T x, T y) { return matrix3x2(x, 0,0,y, 0 ,0 ); }
static matrix3x2 get_scale(T s) { return matrix3x2(s ,0,0,s ,0 ,0 ); }
T a,b,c,d,e,f;
};
template <typename T> BOOST_FORCEINLINE
matrix3x2<T> operator*(const matrix3x2<T>& m1, const matrix3x2<T>& m2) {
return matrix3x2<T>(
m1.a * m2.a + m1.b * m2.c,
m1.a * m2.b + m1.b * m2.d,
m1.c * m2.a + m1.d * m2.c,
m1.c * m2.b + m1.d * m2.d,
m1.e * m2.a + m1.f * m2.c + m2.e,
m1.e * m2.b + m1.f * m2.d + m2.f );
}
template <typename T, typename F>
BOOST_FORCEINLINE
point<F> operator*(point<T> const& p, matrix3x2<F> const& m)
{
return { m.a*p.x + m.c*p.y + m.e, m.b*p.x + m.d*p.y + m.f };
}
////////////////////////////////////////////////////////////////////////////////////////
/// Define affine mapping that transforms the source coordinates by the affine transformation
////////////////////////////////////////////////////////////////////////////////////////
/*
template <typename MapFn>
concept MappingFunctionConcept {
typename mapping_traits<MapFn>::result_type; where PointNDConcept<result_type>;
template <typename Domain> { where PointNDConcept<Domain> }
result_type transform(MapFn&, const Domain& src);
};
*/
template <typename T> struct mapping_traits;
template <typename F>
struct mapping_traits<matrix3x2<F>>
{
using result_type = point<F>;
};
template <typename F, typename F2>
BOOST_FORCEINLINE
point<F> transform(matrix3x2<F> const& mat, point<F2> const& src)
{
return src * mat;
}
}} // namespace boost::gil
#endif

View File

@@ -0,0 +1,149 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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_ALGORITHM_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
#include <boost/gil/extension/numeric/pixel_numeric_operations.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
#endif

View File

@@ -0,0 +1,147 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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_CHANNEL_NUMERIC_OPERATIONS_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
#include <boost/gil/channel.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
#endif

View File

@@ -0,0 +1,217 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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_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/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
#endif

View File

@@ -0,0 +1,118 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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/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
#endif

View File

@@ -0,0 +1,172 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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_PIXEL_NUMERIC_OPERATIONS_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
#include <boost/gil/extension/numeric/channel_numeric_operations.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
#endif

View File

@@ -0,0 +1,143 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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_RESAMPLE_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_RESAMPLE_HPP
#include <boost/gil/extension/numeric/affine.hpp>
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
#include <algorithm>
#include <functional>
namespace boost { namespace gil {
// Support for generic image resampling
// NOTE: The code is for example use only. It is not optimized for performance
///////////////////////////////////////////////////////////////////////////
////
//// resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
////
///////////////////////////////////////////////////////////////////////////
template <typename MapFn> struct mapping_traits {};
/// \brief Set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
/// \ingroup ImageAlgorithms
///
/// The provided implementation works for 2D image views only
template <typename Sampler, // Models SamplerConcept
typename SrcView, // Models RandomAccess2DImageViewConcept
typename DstView, // Models MutableRandomAccess2DImageViewConcept
typename MapFn> // Models MappingFunctionConcept
void resample_pixels(const SrcView& src_view, const DstView& dst_view, const MapFn& dst_to_src, Sampler sampler=Sampler())
{
typename DstView::point_t dst_dims=dst_view.dimensions();
typename DstView::point_t dst_p;
for (dst_p.y=0; dst_p.y<dst_dims.y; ++dst_p.y) {
typename DstView::x_iterator xit = dst_view.row_begin(dst_p.y);
for (dst_p.x=0; dst_p.x<dst_dims.x; ++dst_p.x) {
sample(sampler, src_view, transform(dst_to_src, dst_p), xit[dst_p.x]);
}
}
}
///////////////////////////////////////////////////////////////////////////
////
//// resample_pixels when one or both image views are run-time instantiated.
////
///////////////////////////////////////////////////////////////////////////
namespace detail {
template <typename Sampler, typename MapFn>
struct resample_pixels_fn : public binary_operation_obj<resample_pixels_fn<Sampler,MapFn> > {
MapFn _dst_to_src;
Sampler _sampler;
resample_pixels_fn(const MapFn& dst_to_src, const Sampler& sampler) : _dst_to_src(dst_to_src), _sampler(sampler) {}
template <typename SrcView, typename DstView> BOOST_FORCEINLINE void apply_compatible(const SrcView& src, const DstView& dst) const {
resample_pixels(src, dst, _dst_to_src, _sampler);
}
};
}
/// \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())
{
apply_operation(src, std::bind(
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
std::placeholders::_1,
dst));
}
/// \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())
{
using namespace std::placeholders;
apply_operation(dst, std::bind(
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
src,
std::placeholders::_1));
}
/// \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));
}
///////////////////////////////////////////////////////////////////////////
////
//// resample_subimage: copy into the destination a rotated rectangular region from the source, rescaling it to fit into the destination
////
///////////////////////////////////////////////////////////////////////////
// Extract into dst the rotated bounds [src_min..src_max] rotated at 'angle' from the source view 'src'
// The source coordinates are in the coordinate space of the source image
// Note that the views could also be variants (i.e. any_image_view)
template <typename Sampler, typename SrcMetaView, typename DstMetaView>
void resample_subimage(const SrcMetaView& src, const DstMetaView& dst,
double src_min_x, double src_min_y,
double src_max_x, double src_max_y,
double angle, const Sampler& sampler=Sampler()) {
double src_width = std::max<double>(src_max_x - src_min_x - 1,1);
double src_height = std::max<double>(src_max_y - src_min_y - 1,1);
double dst_width = std::max<double>((double)(dst.width()-1),1);
double dst_height = std::max<double>((double)(dst.height()-1),1);
matrix3x2<double> mat =
matrix3x2<double>::get_translate(-dst_width/2.0, -dst_height/2.0) *
matrix3x2<double>::get_scale(src_width / dst_width, src_height / dst_height)*
matrix3x2<double>::get_rotate(-angle)*
matrix3x2<double>::get_translate(src_min_x + src_width/2.0, src_min_y + src_height/2.0);
resample_pixels(src,dst,mat,sampler);
}
///////////////////////////////////////////////////////////////////////////
////
//// resize_view: Copy the source view into the destination, scaling to fit
////
///////////////////////////////////////////////////////////////////////////
template <typename Sampler, typename SrcMetaView, typename DstMetaView>
void resize_view(const SrcMetaView& src, const DstMetaView& dst, const Sampler& sampler=Sampler()) {
resample_subimage(src,dst,0.0,0.0,(double)src.width(),(double)src.height(),0.0,sampler);
}
} } // namespace boost::gil
#endif // BOOST_GIL_EXTENSION_NUMERIC_RESAMPLE_HPP

View File

@@ -0,0 +1,189 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// 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_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>
namespace boost { namespace gil {
// Nearest-neighbor and bilinear image samplers.
// NOTE: The code is for example use only. It is not optimized for performance
///////////////////////////////////////////////////////////////////////////
////
//// resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
////
///////////////////////////////////////////////////////////////////////////
/*
template <typename Sampler>
concept SamplerConcept {
template <typename DstP, // Models PixelConcept
typename SrcView, // Models RandomAccessNDImageViewConcept
typename S_COORDS> // Models PointNDConcept, where S_COORDS::num_dimensions == SrcView::num_dimensions
bool sample(const Sampler& s, const SrcView& src, const S_COORDS& p, DstP result);
};
*/
/// \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
/// \ingroup ImageAlgorithms
struct nearest_neighbor_sampler {};
template <typename DstP, typename SrcView, typename F>
bool sample(nearest_neighbor_sampler, SrcView const& src, point<F> const& p, DstP& result)
{
typename SrcView::point_t center(iround(p));
if (center.x >= 0 && center.y >= 0 && center.x < src.width() && center.y < src.height())
{
result=src(center.x,center.y);
return true;
}
return false;
}
struct cast_channel_fn {
template <typename SrcChannel, typename DstChannel>
void operator()(const SrcChannel& src, DstChannel& dst) {
using dst_value_t = typename channel_traits<DstChannel>::value_type;
dst = dst_value_t(src);
}
};
template <typename SrcPixel, typename DstPixel>
void cast_pixel(const SrcPixel& src, DstPixel& dst) {
static_for_each(src,dst,cast_channel_fn());
}
namespace detail {
template <typename Weight>
struct add_dst_mul_src_channel {
Weight _w;
add_dst_mul_src_channel(Weight w) : _w(w) {}
template <typename SrcChannel, typename DstChannel>
void operator()(const SrcChannel& src, DstChannel& dst) const {
dst += DstChannel(src*_w);
}
};
// dst += DST_TYPE(src * w)
template <typename SrcP,typename Weight,typename DstP>
struct add_dst_mul_src {
void operator()(const SrcP& src, Weight weight, DstP& dst) const {
static_for_each(src,dst, add_dst_mul_src_channel<Weight>(weight));
// pixel_assigns_t<DstP,DstP&>()(
// pixel_plus_t<DstP,DstP,DstP>()(
// pixel_multiplies_scalar_t<SrcP,Weight,DstP>()(src,weight),
// dst),
// dst);
}
};
} // namespace detail
/// \brief A sampler that sets the destination pixel as the bilinear interpolation of the four closest pixels from the source.
/// If outside the bounds, it doesn't change the destination
/// \ingroup ImageAlgorithms
struct bilinear_sampler {};
template <typename DstP, typename SrcView, typename F>
bool sample(bilinear_sampler, SrcView const& src, point<F> const& p, DstP& result)
{
using SrcP = typename SrcView::value_type;
point_t p0(ifloor(p.x), ifloor(p.y)); // the closest integer coordinate top left from p
point<F> frac(p.x-p0.x, p.y-p0.y);
if (p0.x < -1 || p0.y < -1 || p0.x>=src.width() || p0.y>=src.height())
{
return false;
}
pixel<F,devicen_layout_t<num_channels<SrcView>::value> > mp(0); // suboptimal
typename SrcView::xy_locator loc=src.xy_at(p0.x,p0.y);
if (p0.x == -1)
{
if (p0.y == -1)
{
// the top-left corner pixel
++loc.y();
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], 1 ,mp);
}
else if (p0.y+1<src.height())
{
// on the first column, but not the top-left nor bottom-left corner pixel
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], (1-frac.y),mp);
++loc.y();
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.y ,mp);
}
else
{
// the bottom-left corner pixel
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], 1 ,mp);
}
}
else if (p0.x+1<src.width())
{
if (p0.y == -1)
{
// on the first row, but not the top-left nor top-right corner pixel
++loc.y();
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x) ,mp);
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x ,mp);
}
else if (p0.y+1<src.height())
{
// most common case - inside the image, not on the frist nor last row/column
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x)*(1-frac.y),mp);
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);
++loc.y();
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x)* frac.y ,mp);
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x * frac.y ,mp);
}
else
{
// on the last row, but not the bottom-left nor bottom-right corner pixel
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x) ,mp);
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x ,mp);
}
}
else
{
if (p0.y == -1)
{
// the top-right corner pixel
++loc.y();
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, 1 ,mp);
}
else if (p0.y+1<src.height())
{
// on the last column, but not the top-right nor bottom-right corner pixel
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.y),mp);
++loc.y();
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, frac.y ,mp);
}
else
{
// the bottom-right corner pixel
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, 1 ,mp);
}
}
// Convert from floating point average value to the source type
SrcP src_result;
cast_pixel(mp,src_result);
color_convert(src_result, result);
return true;
}
}} // namespace boost::gil
#endif