146#ifndef VSPLINE_TRANSFORM_H
147#define VSPLINE_TRANSFORM_H
209template <
typename unary_functor_type ,
210 unsigned int dimension >
212 const vigra::MultiArrayView
214 typename unary_functor_type::in_type
216 vigra::MultiArrayView
218 typename unary_functor_type::out_type
226 if ( output.shape() != input.shape() )
229 (
"transform: the shapes of the input and output array do not match" ) ;
240 coupled_functor_type coupled_functor ( functor ) ;
245 typedef typename coupled_functor_type::in_type src_type ;
246 typedef typename coupled_functor_type::out_type trg_type ;
248 typedef vigra::MultiArrayView < dimension , src_type > src_view_type ;
249 typedef vigra::MultiArrayView < dimension , trg_type > trg_view_type ;
251 wielding::coupled_wield < coupled_functor_type , dimension >
253 (src_view_type*)(&input) ,
254 (trg_view_type*)(&output) ,
284template <
typename sink_functor_type ,
285 unsigned int dimension >
286void reduce (
const sink_functor_type & functor ,
287 const vigra::MultiArrayView
289 typename sink_functor_type::in_type
306 < sink_functor_type > adapted_functor_type ;
307 adapted_functor_type adapted_functor ( functor ) ;
312 typedef typename adapted_functor_type::in_type src_type ;
314 typedef vigra::MultiArrayView < dimension , src_type > src_view_type ;
318 wielding::value_reduce < adapted_functor_type , dimension >
320 (src_view_type*)(&input) ,
432template <
class unary_functor_type >
434 vigra::MultiArrayView
435 < unary_functor_type::dim_in ,
436 typename unary_functor_type::out_type
441 enum { dimension = unary_functor_type::dim_in } ;
446 index_functor_type index_functor ( functor ) ;
451 typedef typename index_functor_type::out_type trg_type ;
452 typedef vigra::MultiArrayView < dimension , trg_type > trg_view_type ;
456 wielding::index_wield < index_functor_type , dimension >
458 (trg_view_type*)(&output) ,
479template <
typename sink_functor_type >
480void reduce (
const sink_functor_type & functor ,
481 typename std::conditional
482 < ( sink_functor_type::dim_in == 1 ) ,
484 vigra::TinyVector < int , sink_functor_type::dim_in >
490 enum { dimension = sink_functor_type::dim_in } ;
495 < sink_functor_type > adapted_functor_type ;
497 adapted_functor_type adapted_functor ( functor ) ;
502 typename sink_functor_type::in_nd_ele_type nd_shape ( shape ) ;
504 wielding::index_reduce < adapted_functor_type , dimension >
529template <
typename unary_functor_type ,
530 unsigned int dimension >
531void apply (
const unary_functor_type & ev ,
532 vigra::MultiArrayView
534 typename unary_functor_type::out_type >
542 static_assert ( std::is_same <
typename unary_functor_type::in_type ,
543 typename unary_functor_type::out_type > :: value ,
544 "apply: functor's input and output type must be the same" ) ;
548 transform ( ev , output , output , njobs , p_cancel ) ;
553template <
unsigned int dimension >
554using bcv_type = vigra::TinyVector < vspline::bc_code , dimension > ;
594template <
typename original_type ,
595 typename result_type ,
597 unsigned int cf_dimension ,
598 unsigned int trg_dimension ,
599 int bcv_dimension = cf_dimension >
600void remap (
const vigra::MultiArrayView
601 < cf_dimension , original_type > & input ,
602 const vigra::MultiArrayView
604 vigra::MultiArrayView
605 < trg_dimension , result_type > & output ,
612 static_assert ( vigra::ExpandElementResult < original_type > :: size
613 == vigra::ExpandElementResult < result_type > :: size ,
614 "input and output data type must have same nr. of channels" ) ;
616 static_assert ( cf_dimension
617 == vigra::ExpandElementResult < coordinate_type > :: size ,
618 "coordinate type must have the same dimension as input array" ) ;
624 static_assert ( cf_dimension
626 "boundary condition specification needs same dimension as input array" ) ;
630 if ( output.shape() != coordinates.shape() )
633 (
"the shapes of the coordinate array and the output array must match" ) ;
638 typedef typename vigra::PromoteTraits < original_type , result_type >
639 :: Promote _cf_type ;
641 typedef typename vigra::NumericTraits < _cf_type >
642 :: RealPromote cf_type ;
660 typedef typename vigra::ExpandElementResult < coordinate_type > :: type
rc_type ;
662 auto ev = vspline::make_safe_evaluator < spline_type , rc_type > ( bsp ) ;
667 transform ( ev , coordinates , output , njobs , p_cancel ) ;
696template <
unsigned int dimension ,
typename rc_ele_type =
float >
699 < vigra::MultiArrayView < 1 , rc_ele_type > ,
716template <
typename ET >
721 static const size_t dimension = evaluator_type::dimension ;
723 static const size_t channels = evaluator_type::channels ;
728 typedef typename evaluator_type::out_type
out_type ;
731 typedef typename evaluator_type::out_v
out_v ;
737 typedef typename evaluator_type::rc_ele_type
rc_type ;
738 typedef vigra::MultiArrayView
740 typedef vigra::TinyVector < size_t , dimension >
shape_type ;
797 vigra::MultiArray < 2 , weight_type >
weight ;
804 vigra::MultiArray < 2 , weight_v , allocator_t >
vweight ;
833 for (
size_t d = 0 ; d <
dimension ; d++ )
841 vweight [ vigra::Shape2 ( k , d ) ]
842 =
weight [ vigra::Shape2 ( k , d ) ]
858 for (
auto & wvr : w_line )
892 vigra::TinyVector < int , dimension >
893 estride (
itp.inner.get_estride() ) ;
919 for (
int c = 0 ; c <
shape [ d ] ; c++ )
922 (
grid [ d ] [ c ] , select , tune ) ;
924 itp.inner.obtain_weights
927 grid_ofs [ d ] [ c ] = select * estride [ d ] ;
945 for (
size_t e = 0 ; e <
vsize ; e++ )
967 template <
typename = std::enable_if < ( vsize > 1 ) > >
995 typedef typename inner_type::trg_type trg_t ;
997 < trg_t ,
vsize > :: type trg_v ;
999 trg_v & nd_result =
reinterpret_cast < trg_v &
> ( result ) ;
1003 itp.inner.eval ( select ,
vweight , nd_result ) ;
1027 typedef typename inner_type::trg_type trg_t ;
1028 trg_t & nd_result =
reinterpret_cast < trg_t &
> ( result ) ;
1029 itp.inner.eval ( select ,
weight , nd_result ) ;
1039 void eval ( vigra::MultiArrayView < 1 , out_ele_v > & vresult ,
1040 vigra::MultiArrayView < 1 , out_type > & leftover )
1043 assert ( leftover.shape(0) ==
rest ) ;
1056 for (
size_t ch = 0 ; ch <
channels ; ch++ )
1057 vresult [ a *
channels + ch ] = ndvr [ ch ] ;
1059 for (
size_t a = 0 ; a <
rest ; a++ )
1061 eval ( leftover[a] ) ;
1065 void eval ( vigra::MultiArrayView < 1 , out_type > & result )
1067 assert ( result.shape(0) ==
shape [
axis ] ) ;
1069 for (
size_t a = 0 ; a <
shape [
axis ] ; a++ )
1071 eval ( result[a] ) ;
1116template <
typename functor_type >
1119 typename functor_type::in_ele_type > & grid ,
1120 const functor_type & functor ,
1121 vigra::MultiArrayView < functor_type::dim_in ,
1122 typename functor_type::out_type >
1146template <
typename _inner_type ,
1150 < typename vspline::canonical_type
1151 < ic_type , _inner_type::dim_in > ,
1152 typename _inner_type::out_type ,
1153 _inner_type::vsize >
1165 typedef typename inner_type::in_ele_type
rc_type ;
1170 static_assert ( std::is_integral < ic_type > :: value ,
1171 "grid_eval_functor: must use integral coordinates" ) ;
1175 typedef grid_spec < inner_type::dim_in ,
1188 typename inner_type::in_type cc ;
1195 typedef typename inner_type::in_nd_ele_type nd_rc_type ;
1197 const nd_ic_type & nd_c (
reinterpret_cast < const nd_ic_type &
> ( c ) ) ;
1198 nd_rc_type & nd_cc (
reinterpret_cast < nd_rc_type &
> ( cc ) ) ;
1201 nd_cc [ d ] =
grid [ d ] [ nd_c[d] ] ;
1203 inner.eval ( cc , result ) ;
1206 template <
typename = std::enable_if < ( vsize > 1 ) > >
1210 typename inner_type::in_v cc ;
1213 typedef typename inner_type::in_nd_ele_v nd_rc_v ;
1215 const nd_ic_v & nd_c (
reinterpret_cast < const nd_ic_v &
> ( c ) ) ;
1216 nd_rc_v & nd_cc (
reinterpret_cast < nd_rc_v &
> ( cc ) ) ;
1224 for (
int e = 0 ; e <
vsize ; e++ )
1225 nd_cc[d][e] =
grid[d][ nd_c[d][e] ] ;
1227 inner.eval ( cc , result ) ;
1240template <
typename functor_type >
1243 typename functor_type::in_ele_type > & grid ,
1244 const functor_type & functor ,
1245 vigra::MultiArrayView < functor_type::dim_in ,
1246 typename functor_type::out_type >
1293template <
typename functor_type >
1295 typename functor_type::in_ele_type > & grid ,
1296 const functor_type & functor ,
1297 vigra::MultiArrayView < functor_type::dim_in ,
1298 typename functor_type::out_type >
1306 for (
int d = 0 ; d < functor_type::dim_in ; d++ )
1307 assert ( grid[d].size() >= result.shape ( d ) ) ;
1309 using uses_spline_t =
typename
1310 std::is_base_of < bspline_evaluator_tag , functor_type > :: type ;
1313 njobs , p_cancel ) ;
1322template <
typename functor_type >
1324 typename functor_type::in_ele_type > & grid ,
1325 const functor_type & functor ,
1326 vigra::MultiArrayView < 1 ,
1327 typename functor_type::out_type >
1333 assert ( grid[0].size() >= result.shape ( 0 ) ) ;
1340template <
typename functor_type >
1342 typename functor_type::in_ele_type > & grid ,
1343 const functor_type & functor ,
1344 vigra::MultiArrayView < functor_type::dim_in ,
1345 typename functor_type::out_type >
1350 static const bool is_1d ( functor_type::dim_in == 1 ) ;
1352 transform ( grid , functor , result , njobs , p_cancel ,
1353 std::integral_constant < bool , is_1d > () ) ;
1359template <
typename functor_type >
1361 typename functor_type::in_ele_type > & grid ,
1362 const functor_type & functor ,
1363 vigra::MultiArrayView < functor_type::dim_in ,
1364 typename functor_type::out_type >
1369 transform ( grid , functor , result , njobs , p_cancel ) ;
1375template <
typename functor_type >
1377 typename functor_type::in_ele_type > & grid ,
1378 const functor_type & functor ,
1379 vigra::MultiArrayView < functor_type::dim_in ,
1380 typename functor_type::out_type >
1385 transform ( grid , functor , result , njobs , p_cancel ) ;
1419template <
unsigned int dimension ,
1420 typename value_type ,
1421 typename math_ele_type
1422 =
typename vigra::NumericTraits
1423 <
typename vigra::ExpandElementResult
1424 < value_type > :: type
1430 vigra::MultiArrayView < dimension , value_type > & target )
1432 if ( target.shape() != bspl.
core.shape() )
1434 (
"restore: spline's core shape and target array shape must match" ) ;
1443 if ( (
void*) ( bspl.
core.data() ) != (
void*) ( target.data() ) )
1446 target = bspl.
core ;
1454 int headroom = degree / 2 ;
1455 int ksize = headroom * 2 + 1 ;
1459 vigra::MultiArray < 1 , xlf_type > kernel ( ksize ) ;
1482 std::vector < vspline::fir_filter_specs > vspecs ;
1484 for (
int axis = 0 ; axis < dimension ; axis++ )
1488 ( bspl.
bcv [ axis ] , ksize , headroom , kernel.data() ) ) ;
1506 < value_type , value_type , dimension , filter_type >
1507 ( bspl.
core , target , vspecs ) ;
1516template <
int dimension ,
1517 typename value_type ,
1518 typename math_ele_type
1519 =
typename vigra::NumericTraits
1520 <
typename vigra::ExpandElementResult
1521 < value_type > :: type
1527 restore < dimension , value_type , math_ele_type , vsize >
1528 ( bspl , bspl.
core ) ;
vigra::TinyVector< float, 2 > coordinate_type
vspline::bspline< pixel_type, 2 > spline_type
separable convolution of nD arrays
code to evaluate uniform b-splines
code to distribute the processing of bulk data to several threads
void transform(std::true_type, grid_spec< functor_type::dim_in, typename functor_type::in_ele_type > &grid, const functor_type &functor, vigra::MultiArrayView< functor_type::dim_in, typename functor_type::out_type > &result, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
given the generator functor 'grev_generator' (above), performing the grid_eval becomes trivial: const...
void reduce(const sink_functor_type &functor, const vigra::MultiArrayView< dimension, typename sink_functor_type::in_type > &input, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
reduce function processing by value. sink_functor_type is a functor taking values (which are loaded f...
void get_kernel(const int °ree, vigra::MultiArrayView< 1, target_type > &kernel, const bool &odd=true)
this function deposits the reconstruction kernel in the array 'kernel'. This kernel can be used to co...
void transform(const unary_functor_type &functor, const vigra::MultiArrayView< dimension, typename unary_functor_type::in_type > &input, vigra::MultiArrayView< dimension, typename unary_functor_type::out_type > &output, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
implementation of two-array transform using wielding::coupled_wield.
void filter(const vigra::MultiArrayView< D, in_type > &input, vigra::MultiArrayView< D, out_type > &output, types ... args)
vspline::filter is the common entry point for filter operations in vspline. This routine does not yet...
typename vigra::ExpandElementResult< T > ::type ET
using definition for the 'elementary type' of a type via vigra's ExpandElementResult mechanism....
void apply(const unary_functor_type &ev, vigra::MultiArrayView< dimension, typename unary_functor_type::out_type > &output, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
we code 'apply' as a special variant of 'transform' where the output is also used as input,...
void restore(const vspline::bspline< value_type, dimension > &bspl, vigra::MultiArrayView< dimension, value_type > &target)
restore restores the original data from the b-spline coefficients. This is done efficiently using a s...
void gen_grid_eval(grid_spec< functor_type::dim_in, typename functor_type::in_ele_type > &grid, const functor_type &functor, vigra::MultiArrayView< functor_type::dim_in, typename functor_type::out_type > &result, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
for backward compatibility, we provide 'gen_grid_eval'. This is deprecated and will eventually go awa...
vigra::TinyVector< vspline::bc_code, dimension > bcv_type
a type for a set of boundary condition codes, one per axis
typename std::conditional< N==1, ET< T >, vigra::TinyVector< ET< T >, N > > ::type canonical_type
produce the 'canonical type' for a given type T. If T is single-channel, this will be the elementary ...
typename vector_traits< T, N > ::type simdized_type
this alias is used as a shorthand to pick the vectorized type for a given type T and a size N from 'v...
void remap(const vigra::MultiArrayView< cf_dimension, original_type > &input, const vigra::MultiArrayView< trg_dimension, coordinate_type > &coordinates, vigra::MultiArrayView< trg_dimension, result_type > &output, bcv_type< bcv_dimension > bcv=bcv_type< bcv_dimension >(MIRROR), int degree=3, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
Implementation of 'classic' remap, which directly takes an array of values and remaps it,...
void grid_eval(grid_spec< functor_type::dim_in, typename functor_type::in_ele_type > &grid, const functor_type &functor, vigra::MultiArrayView< functor_type::dim_in, typename functor_type::out_type > &result, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
for backward compatibility, we provide 'grid_eval'. This is deprecated and will eventually go away,...
vigra::TinyVector< vigra::MultiArrayView< 1, rc_ele_type >, dimension > grid_spec
void generate_wield(const functor_type functor, vigra::MultiArrayView< dimension, typename functor_type::out_type > &output, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
generate_wield uses a generator function to produce data. Inside vspline, this is used for grid_eval,...
precalculated prefilter poles and basis function values
vspline creates vigra::MultiArrays of vectorized types. As long as the vectorized types are Vc::SimdA...
class bspline now builds on class bspline_base, adding coefficient storage, while bspline_base provid...
void prefilter(vspline::xlf_type boost=vspline::xlf_type(1), int njobs=vspline::default_njobs)
prefilter converts the knot point data in the 'core' area into b-spline coefficients....
class convolve provides the combination of class fir_filter above with a vector-friendly buffer....
we need a 'generator functor' to implement grid_eval using the code in wielding.h....
vigra::MultiArrayView< dimension, typename evaluator_type::trg_type > target_type
vspline::vector_traits< weight_type, vsize >::type weight_v
vigra::MultiArray< 2, weight_type > weight
static const size_t vsize
vspline::vector_traits< int, vsize >::type ofs_ele_v
evaluator_type::math_ele_type weight_type
grev_generator(const vspline::grid_spec< dimension, rc_type > &_grid, const evaluator_type &_itp, size_t _axis, shape_type _shape)
evaluator_type::rc_ele_type rc_type
void reset(shape_type crd, size_t _aggregates)
typename vspline::allocator_traits< weight_v > ::type allocator_t
static const size_t dimension
vigra::TinyVector< size_t, dimension > shape_type
evaluator_type::out_ele_v out_ele_v
evaluator_type::inner_type inner_type
vigra::MultiArray< 2, weight_v, allocator_t > vweight
weight_type * shuffled_weights
vspline::grid_spec< dimension, rc_type > grid_spec_type
evaluator_type::out_ele_type out_ele_type
evaluator_type::out_v out_v
void eval(out_type &result)
void eval(vigra::MultiArrayView< 1, out_type > &result)
evaluator_type::out_type out_type
evaluator_type::out_nd_ele_type out_nd_ele_type
void eval(vigra::MultiArrayView< 1, out_ele_v > &vresult, vigra::MultiArrayView< 1, out_type > &leftover)
int * grid_ofs[dimension]
evaluator_type::out_nd_ele_v out_nd_ele_v
const grid_spec_type & grid
static const size_t channels
const evaluator_type & itp
weight_type * grid_weight[dimension]
grid_eval_functor is used for 'generalized' grid evaluation, where the functor passed in is not a bsp...
grid_eval_functor(grid_spec_t &_grid, const inner_type &_inner)
void eval(const in_type &c, out_type &result) const
inner_type::in_ele_type rc_type
vspline::canonical_type< ic_type, dimension > in_type
vspline::unary_functor< in_type, out_type, vsize > base_type
grid_spec< inner_type::dim_in, typename inner_type::in_ele_type > grid_spec_t
void eval(const typename base_type::in_v &c, typename base_type::out_v &result) const
inner_type::out_type out_type
fir_filter_specs holds the parameters for a filter performing a convolution along a single axis....
shape mismatch is the exception which is thrown if the shapes of an input array and an output array d...
class unary_functor provides a functor object which offers a system of types for concrete unary funct...
vigra::TinyVector< in_ele_type, dim_in > in_nd_ele_type
vector_traits< IN, vsize >::nd_ele_v in_nd_ele_v
vector_traits< IN, vsize >::type in_v
vectorized in_type and out_type. vspline::vector_traits supplies these types so that multidimensional...
vector_traits< OUT, vsize >::type out_v
with the definition of 'simd_traits', we can proceed to implement 'vector_traits': struct vector_trai...
vs_adapter wraps a vspline::unary_functor to produce a functor which is compatible with the wielding ...
same procedure for a vspline::sink_type
Implementation of vspline::transform.