template<dip::uint N, typename TPI, typename F>
dip::Framework::VariadicScanLineFilter class

An implementation of the ScanLinefilter for N input images and 1 output image.


Here, all buffers are of the same data type, and the scalar operation applied to each sample is the lambda function of type F, passed to the constructor. All input and output images must have the same number of tensor elements, and in the same order.

When N = 1, the resulting object can be passed to the dip::Framework::ScanMonadic function. When N = 2, you can use the dip::Framework::ScanDyadic function. For any other N, or when dip::Framework::ScanDyadic does not do the right thing, use dip::Framework::Scan.

The following example shows how to make a dyadic operator that performs computations in sfloat and generates an output image of that same type.

dip::Image lhs = ...;
dip::Image rhs = ...;
dip::Image out;
dip::dfloat offset = 40;
auto sampleOperator = [ = ]( std::array< dip::sfloat const*, 2 > its ) { return ( *its[ 0 ] * 100 ) / ( *its[ 1 ] * 10 ) + offset; };
dip::Framework::VariadicScanLineFilter< 2, dip::sfloat, decltype( sampleOperator ) > scanLineFilter( sampleOperator );
dip::Framework::ScanDyadic( lhs, rhs, out, dip::DT_SFLOAT, dip::DT_SFLOAT, scanLineFilter );

sampleOperator is a lambda function, which captures offset by value (note that capturing by reference will slow down the execution significantly). It has a single input argument, a std::array of 2 float pointers. The first pointer will point at a sample in the lhs input image, and the second to the corresponding sample in the rhs input image. The return value of the lambda will be assigned to the corresponding sample in the output image. Note that to access the sample values, you need to use the syntax *its[ 0 ], where the 0 is the index into the array, yielding a pointer, which is dereferenced by the * operator to access the sample value.

To use the VariadicScanLineFilter with dynamic data type dispatch, it is necessary to use an auxiliary function. Such an auxiliary function also simplifies the use of the class template:

template< typename TPI, typename F >
std::unique_ptr< dip::Framework::ScanLineFilter > NewFilter( F func ) {
   return static_cast< std::unique_ptr< dip::Framework::ScanLineFilter >>( new dip::Framework::VariadicScanLineFilter< 1, TPI, F >( func ));
// ...
dip::Image in = ...;
dip::Image out;
dip::DataType dt = in.DataType();
std::unique_ptr< dip::Framework::ScanLineFilter > scanLineFilter;
DIP_OVL_CALL_ASSIGN_REAL( scanLineFilter, NewFilter, (
      [ = ]( auto its ) { return ( std::cos( *its[ 0 ] ) * 100 ) + offset; }
), dt );
dip::Framework::ScanMonadic( in, out, dt, dt, in.TensorElements(), *scanLineFilter, dip::Framework::ScanOption::TensorAsSpatialDim );

Notice in this case we used a generic lambda, i.e. its input parameter has type auto. It will be compiled differently for each allowed data type. The function template NewFilter that we defined specifies the N in the VariadicScanLineFilter template, and helps pass on the type of the lambda, which is automatically determined by the compiler and filled out. That is, the function can be called as NewFilter< dip::sfloat >( sampleOperator ). The object is allocated in free memory, and its lifetime is managed by std::unique_ptr, meaning that there is no need to explicitly delete the object. Next, we use the DIP_OVL_CALL_ASSIGN_REAL macro to call different instantiations of our function, depending on the data type dt, which we determine dynamically from the input image. The output is captured in a variable and passed to the scan function.

For values of N from 1 to 4 there are pre-defined functions just like the NewFilter function above: dip::Framework::NewMonadicScanLineFilter, dip::Framework::NewDyadicScanLineFilter, dip::Framework::NewTriadicScanLineFilter, dip::Framework::NewTetradicScanLineFilter. These functions take an optional second input argument cost, which specifies the cost in cycles to execute a single call of func. This cost is used to determine if it’s worthwhile to parallelize the operation, see Multithreading.

Base classes

class dip::Framework::ScanLineFilter abstract
Prototype line filter for dip::Framework::Scan.