by Cris Luengo
DIPlib 3 is a complete rewrite in C++ of the DIPlib 2 infrastructure, which was written in C; only the code that implements actual image processing and analysis algorithms is ported over.
Here we list the changes to DIPlib as compared to version 2.9. The list below describes infrastructure changes, function interface changes, and functionality changes in the DIPlib library. It is possible that we missed some changes here, but hopefully this list will help in porting your old code that used DIPlib to the new version.
Functions and types used to start with
dip_, now they are in the
Functions no longer return a
dip_Error, they throw an exception instead. The
et al. macros are gone. So are the
The array types are now based on either
is a short-array optimized version of
std::vector with a bunch of specialized algorithms
as member functions. Consequently, all access functions are no longer, to be replaced by
methods with different names and syntax.
The core image class,
dip_Image, now is
dip::Image, with a much simplified interface.
As with the array types, access functions are no longer, to be replaced by class methods.
Many of these class methods have names similar to the original access functions, but not
always. For example,
dip_ImageSetStride now is
dip_Assimilate is the
We used to call the image size its dimension.
dip_Dimensions is now
The reason is that it was too confusing talking about a dimension as an image axis (the
2nd dimension), and the dimension of that dimension (the size of the image along that
Images now can have a tensor as pixel value, as was possible in DIPimage. To port old
functions, you can test for
dip::Image::IsScalar and ignore this new feature, or
modify the old function to work with tensor values.
Images now carry the physical dimension in them (referred to as pixel size). When porting functions, think about whether this data needs to be maintained, modified, or removed.
The same is true for the color space. A function that changes the number of tensor elements must also remove the color space information.
We have added 64-bit signed and unsigned integers to the set of allowed data types for pixels.
Please read the documentation to the
dip::Image class before doing any work with the
dip_PixelTableArrayFrameWork→ doesn’t exist any more, was used meaningfully only in
Their interfaces are not exactly compatible, but it should be relatively straightforward to port old line functions to use the new framework, yielding shorter code. However, all line functions are now expected to use strides.
dip_ovl.h is now
diplib/overload.h, and works like a normal header file defining
macros to use in your code.
dip_tpi.h is gone, the template strategy to define overloaded
functions is now based on C++ templates, yielding code that is easier to write and easier
There is no longer a
dip_Initialise function. There are no registries.
There is only one global variable: the number of threads to use with OpenMP (see
There is no longer a
dip_ImagesSeparate function. Its functionality can be accomplished
using a simple image copy (the copy shares the image data with the original image, and
makes it possible to strip the original image while still keeping the input data available).
Header files used to have names such as
dip_xxx.h, they now are
diplib/xxx.h. The “
part has remained the same in most cases, though some function declarations have moved to a
different header file. The documentation specifies which header file to include for each
dipio_Xxxfunctions are now defined in the
diplib/file_io.hheader file (reading and writing ICS, TIFF and JPEG files).
dipio_Colour2Grayfunctionality is replaced by
dip::ColorSpaceManager. Other functionality no longer exists.
Function parameters expressing options are now represented by strings rather than
enum constants (except for low-level library functionality).
The library now makes a distinction between signed and unsigned integers. This affects many function parameters.
Output arguments are now always on the left-hand side, except for output images.
We try to sort the arguments most commonly left with default values at the end of the argument lists. This caused some functions to have a different parameter order. For example, the boundary condition is not commonly changed, and so the boundary condition array input argument is now typically further to the right in (usually at the end of) the argument list.
Function names are often simplified, since in C++ it’s possible to overload functions for
different types. For example,
dipm_BesselJ0 are now both called
dip_IntegerArrayUseParameter, etc. are
Some other function names that included only parts of a name or verb (they were shortened)
have been renamed to use full names. For example:
dip_Sub is now
dip_LaplaceMinDgg is now called
are now called
dip_Measure is now
dip::MeasurementTool an object
that knows about defined measurement features.
Measurement features are registered with a
dip::MeasurementTool object, not in the
Measurement features have a much simpler programmer’s interface, it should be easier to write new features now.
Computed measurements are now in an object of type
dip::Measurement, whose interface is
much easier to use than the old
dip_ObjectToMeasurement now takes a feature iterator rather than computing the feature;
this might be more flexible.
dip_Compare used to implement all arithmetic and comparison operators,
(with convenience macros
dip_Sub, etc.). These functions no longer exist,
each operator is implemented by its own function. The shortened names of these functions
are no longer shortened, so instead of
dip_AddFloat, etc. now are overloaded versions of
dip::Add et al.
dip_WeightedAdd is now generalized to
dip_WeightedSub can be emulated by setting a negative weight.
dip_WeightedDiv were not used anywhere, and don’t seem very useful.
Morphological filters now use a
dip::StructuringElement to collect three parameters
of DIPlib 2. Other filters that had a filter shape argument now use a
dip::Kernel to collect three parameters.
dip_Max are now
dip::SignedInfimum. There are too many functions with “Maximum” and “Minimum” in
dip_ImageToHistogram have been merged into the
dip::Histogram, which replaces
dip::Distribution is a new class that replaces
dip::Distribution is very different from
dip_ImageLookup function has been merged with the
dip::LookupTable object, and
includes the functionality of
dip_Threshold is now
dip::Threshold is a function that allows
to select an automated threshold method.
dip_RandomXxx functions are now methods to the
and similar functions are now classes
dip::UniformRandomGenerator and similar.
dip::GaussianRandomGenerator produces a single output value, the object stores the
second value for the next call.
dip_PlaneDoEdge are merged into
which additionally can specify the border size.
dip_LocalMinima is now called
dip::WatershedMinima. There’s also a maxima variant.
dip_GetMaximumAndMinimum is now called
dip::MaximumAndMinimum for consistency.
dip_ResamplingFT is no longer a separate function, call
dip_Skewing was renamed to
dip::Skew for consistency.
dip::Rotation2D, and a generalized
dip::Rotation is similar but takes
two additional integers to specify the rotation plane.
dip_Rotation3d are now both called
dip::Rotation3D, their argument types are different.
dip::Rotation and similar now take a boundary condition
as optional argument.
dip::Skew has a new parameter that allows selection of the image
line that has 0 shift.
dip::Rotation now rotates around the pixel at the origin (this is
the pixel to the right of the geometric center for even-sized images), rather than the geometric
center of the image.
dip_Crop are now all
member functions of
dip::Image, and modify the existing image (without copying data).
dip_GetXxx are now all implemented through indexing operations
dip::Image object (see the many overloads of
dip::Image::At) and assignment to
the output of these operations.
dip_KuwaharaImproved is now called
dip_Kuwahara is no longer
(C++ default values make it redundant).
dip_GeneralisedKuwaharaImproved is now called
dip_GeneralisedKuwahara is no longer (C++ default values make it redundant).
dip_PaintEllipsoid are now called
dip::DrawEllipsoid, respectively (for consistency).
dip_DrawLineComplex are now a single function
dip::DrawLine; the same is true for
dip_RadialDistribution renamed to
dip_Bilateral renamed to
dip::FullBilateralFilter. Added new function
an interface to all bilateral filter variants.
dip_TestObjectAddNoise have been merged into a single function:
The new function additionally has the option to generate test objects with Gaussian
edges directly in the spatial domain.
dip_GenerateRamp is now
dip::CreateRamp, and has convenience functions
dip::EuclideanDistanceToPoint and friends now take the sizes of the output image to create. They
are generalized in the functions
dip::ClipHigh are convenience interfaces to
Second order extrapolation boundary extension didn’t do as advertised in DIPlib 2. Also the first order extrapolation didn’t work correctly with unsigned integers. The new implementation fits a 1st or 2nd order polynomial that reaches 0 at the end of the extended boundary, with the 2nd order polynomial matching two samples at the image edge and therefore connects smoothly. A 3rd order extrapolation has been added, which works similarly to the 2nd order extrapolation but reaches 0 smoothly at the end of the boundary. These functions are quite noise sensitive, however, and produce high frequencies along the edge.
The mirror and asymmetric boundary extension methods have been fixed to work correctly when the boundary is larger than the image. Mirror no longer repeats the pixel at the edge of the image.
Fixed little bug in the “Perimeter” measurement feature, which didn’t check the corner count for the transition from the last to the first chain code, yielding a perimeter that was often 0.0910 pixels too long. The feature “Radius” now computes the center of mass of the object correctly.
The measurement features “Skewness” and “ExcessKurtosis” are no longer separate features, but instead put together in the new “Statistics” feature, which also computes the mean and standard deviation. The measurement feature “StdDev” is now called “StandardDeviation”. The algorithms to compute these statistics have changed to be more stable. The measurement feature “Sum” was an alias to “Mass”, and is not (yet?) available.
The measurement feature “Convexity” has been renamed to “Solidity”, the more common name for the ratio of area to convex area.
New measurement features: “SolidArea”, “Circularity”, “Convexity”, “Eccentricity”, “EllipseVariance”, “Roundness”, “DimensionsCube”, “DimensionsEllipsoid”, “GreyDimensionsCube” and “GreyDimensionsEllipsoid”. Note that “Convexity” therefore is not the same as what it was in the previous version of the library.
The measurement features “Mu”, “Inertia”, “MajorAxes”, and their grey-value versions have been generalized to arbitrary number of dimensions.
dip::SeparableConvolution treats input filter definitions slightly differently, and there
no longer are
dip::ImageDisplay no longer does any spatial scaling. Also, it’s a class, not a function, and provides
much more functionality than the function of the same name in the old version of the library.
dip::ColorSpaceManager is functionality ported from MATLAB-code in DIPimage 2,
with a few new color spaces added.
dip::FourierTransform now does normalization in the more common way (forward transform not
normalized, inverse transform normalized by 1/N), but an option (
"symmetric") allows to change
the normalization to be consistent with DIPlib 2, which used a symmetric normalization
scheme (both forward and backward transforms use 1/N1/2). It also has options
to specify where the origin of the transform is (
"corner") and for padding to a nice
dip::Histogram misses a few of the options that
dip_MultiDimensionalHistogram had, but I
don’t think they are relevant. They can be added easily if necessary. Histograms now use
64-bit unsigned integers for the bins. It is possible to add histograms together.
Many threshold selection strategies have been ported from MATLAB code in DIPimage, see
dip::Random uses a different pseudo-random number generator. Previous versions used the
Mersenne Twister. We now use the PCG scheme (permuted linear congruential generator), which
is much faster than the Mersenne Twister, has a much smaller internal state, and produces
better quality randomness, though with the given parameters, the period is not as large as
that of the Mersenne Twister (2128 vs 219937, but do note that
2128 is a very, very long period).
Morphological filters define line structuring elements differently than before. They used to
be available only for 2D images, now they are generalized to nD. The filter parameter, instead
of being a length and an angle, now represents the bounding box, with direction encoded by the
signs. Besides the discrete line and the interpolated line, we now have several other options,
including the periodic line, which makes translation-invariant operations with line SEs much
more efficient. The
"diamond" SE is now implemented using line SEs, and we have added an
"octagonal" SE that is computed as a combination of a diamond SE and a rectangular SE.
dip::Rotation and dependent functions now rotate around the pixel that is right from center
(the same pixel that is assumed the origin in
dip::FourierTransform and other functions),
instead of the point in between pixels, in case of an even-sized image. The implementation is
slightly more complex, but this definition is more useful. This function now works for any
number of dimensions, though it only rotates around one cartesian axis.
a new function that does a full 3D rotation.
dip::Skew can now skew in multiple dimensions at the same time.
dip::Shift now calls
dip::Resampling, shifting the image in the spatial domain.
uses the frequency domain, as
dip::Resampling (and by extension
dip::Shift) shifts the image in the opposite direction
from what it did in DIPlib 2, where the shift was unintuitive.
dip::FindShift now returns the shift with inverse sign compared to before, to match the reversal
dip::Label now returns an unsigend integer image (previously it was a signed integer image).
All functions that work on labeled images expect an unsigned integer image as input.
dip::ImageWriteICS now has a
"fast" option that causes dimensions to be written to file in
the order in which they are stored in memory, rather than in standard increasing order. This
makes writing a lot faster if strides are non-standard.
dip::ImageReadICS has a similar option
that re-orders strides for the output image to match those of the file, again potentially decreasing
reading times significantly.
dip::MaximumSuppression have been generalized from 2D only to any
number of dimensions.
dip::GreyWeightedDistanceTransform now works for images of any dimensionality, and no longer
excludes the pixels at the edge of the image. It also accepts an optional mask image. The Euclidean
distance output argument has been merged with the grey-weighted distance output, a flag is used to
choose which of these two outputs should be given. By default, it now uses the fast marching algorithm,
which produces more isotropic results than the old algorithm.
dip::GrowRegions no longer takes a grey-value image as input. Use
dip::EuclideanDistanceTransform has a new algorithm which produces exact distances in nD, and
is parallelized and very fast. This new algorithm is the default.
dip::ResampleAt has various signatures and a lot more flexibility than in the old library. There
is also a
dip::ResampleAtUnchecked, to be used together with
for low-level use.
dip::OrientationSpace is a simplified version of the old
with only the most useful options.
Documented functions not (yet) ported:
dip_UpperEnvelope. It is unlikely that these will be ported,
unless someone really needs them.
New external library DIPviewer adds interactive image display, see its documentation.
New external library DIPjavaio adds the option to use Bio-Formats to read hundreds of image file formats, see its documentation.
New analysis functions:
New detection functions:
New display functions:
New distance function:
New binary filtering functions:
New linear filtering functions:
New morphological functions:
New nonlinear filtering functions:
New generation functions:
New geometric transformation functions:
New grey-value mapping functions:
New histogram functions:
New labeled regions function:
New math and statistics functions:
New measurement functions: see the class
dip::Measurement, and functions that apply to it:
dip::SampleStatistics. See the classes
New microscopy functions:
New segmentation functions:
New testing functions:
dip::testing::CompareImages. New class:
New transform functions:
There is also a lot of new functionality in the library infrastructure, which we cannot all list here. See the library infrastructure documentation.