Skip to content

Commit 2f0a016

Browse files
committed
Bump version number for 3.5.0 release.
1 parent 3afa432 commit 2f0a016

File tree

4 files changed

+308
-231
lines changed

4 files changed

+308
-231
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ project(DIPlib)
2020

2121
# The version number and latest copyright year. Update these values here, they're used all throughout the project.
2222
set(PROJECT_VERSION_MAJOR "3")
23-
set(PROJECT_VERSION_MINOR "4")
24-
set(PROJECT_VERSION_PATCH "3")
23+
set(PROJECT_VERSION_MINOR "5")
24+
set(PROJECT_VERSION_PATCH "0")
2525
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
2626
set(DIP_COPYRIGHT_YEAR "2024")
2727

changelogs/diplib_3.5.0.md

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
---
2+
layout: post
3+
title: "Changes DIPlib 3.5.0"
4+
---
5+
6+
## Changes to *DIPlib*
7+
8+
### New functionality
9+
10+
- Added `dip::OutputBuffer` as a virtual base class, and `dip::SimpleOutputBuffer` and `dip::FixedOutputBuffer`
11+
as specific instances. These are used to handle a buffer that a JPEG or PNG file can be written into by
12+
`dip::ImageWriteJPEG()` and `dip::ImageWritePNG()`.
13+
14+
- Added `dip::Framework::Projection()` as a public function. Previously it was a private library function for internal
15+
use only. This framework function simplifies the creation of projection operations, and forms the basis of
16+
functions such as `dip::Mean()` and `dip::Maximum()`.
17+
18+
- Added macros `DIP_PARALLEL_ERROR_DECLARE`, `DIP_PARALLEL_ERROR_START` and `DIP_PARALLEL_ERROR_END`
19+
to simplify writing parallel code with OpenMP that properly handles exceptions.
20+
21+
- Added an operator to convert `dip::Units` to `bool`. The units object will test false if it's unitless.
22+
23+
- Added `dip::Quartiles()`.
24+
25+
- Added `dip::Measurement::IteratorFeature::AsImage()` and `AsScalarImage()`.
26+
27+
- Added `dip::Histogram::OptimalConfiguration()` and `OptimalConfigurationWithFullRange()`, which make it possible
28+
to configure the histogram to use the Freedman--Diaconis rule to choose the bin size.
29+
30+
- Added `dip::LabelMap`, a class that holds labels (object IDs) and can map them to new values. The mapping can be
31+
applied to a labeled image or to a `dip::Measurement` object. You can also index into a `dip::Measurement`
32+
object with a `dip::LabelMap`.
33+
34+
- Added comparison operators for `dip::Measurement::IteratorFeature`. They return a `dip::LabelMap`.
35+
36+
- Added `dip::UnionFind::Size()`.
37+
38+
- Added `dip::IsOnEdge()`.
39+
40+
- Added an overload to `dip::GaussianMixtureModel()` that takes a 1D histogram as input.
41+
42+
### Changed functionality
43+
44+
- The `compressionLevel` argument to `dip::ImageWritePNG()` changed from `dip::uint` to `dip::sint`, allowing for
45+
-1 to configure the deflate algorithm to use RLE instead of its default strategy. For some images this option
46+
can lead to smaller files, and for some images to much faster compression.
47+
48+
- The versions of `dip::ImageWriteJPEG()` and `dip::ImageWritePNG()` that write to a memory buffer now take
49+
a version of a `dip::OutputBuffer` object to write to. Overloaded versions of these two functions maintain
50+
the previous syntax where the buffer is created internally and returned to the caller.
51+
52+
- `dip::Framework::Projection()` is now parallelized. All projection functions (for example `dip::Mean()` and
53+
`dip::Maximum()`) now can use multithreading for faster computation if the output has at least one dimension.
54+
For example, the mean value of each image row can be computed in parallel, but the mean value over the whole
55+
image is still not computed in parallel.
56+
57+
- `dip::PairCorrelation()`, `dip::ProbabilisticPairCorrelation()`, `dip::Semivariogram()`, and `dip::ChordLength()`
58+
Have been parallelized for `"random"` sampling.
59+
60+
- `dip::GrowRegionsWeighted()` with a `dip::Metric` parameter has been deprecated. The new version of the function
61+
uses the fast marching algorithm in the grey-weighted distance transform. If both `grey` and `mask` are not
62+
forged, `dip::EuclideanDistanceTransform()` is called instead of `dip::GreyWeightedDistanceTransform()`.
63+
This makes the function efficient for when isotropic growing is required. And the function now has a new float
64+
parameter, `distance` that determines how far the regions are grown.
65+
66+
- `dip::ImageRead()` throws a `dip::RunTimeError` instead of a `dip::ParameterError` if the file doesn't exist
67+
or is of an unrecognized type.
68+
69+
- `dip::GetOptimalDFTSize()` has a new argument `maxFactor` that determines what the largest factor for the output
70+
integer can be. Valid values are 5, 7 and 11. A new function `dip::MaxFactor()` will give the appropriate value
71+
depending on whether a real or complex-valued transform is being computed, and what FFT implementation is being
72+
used. When using *PocketFFT*, this function can now also return much larger values than before.
73+
74+
- `dip::OptimalFourierTransformSize()`, which depends on `dip::GetOptimalDFTSize()` (see the bullet point above
75+
this one) has a new argument `purpose` that can be either `"real"` or `"complex"`, and uses the new
76+
`dip::MaxFactor()` to fill in the `maxFactor` argument.
77+
78+
- `dip::GaussFT()` has a new parameter `boundaryCondition`, the default empty value gives the same behavior as
79+
previously. `dip::Gauss()` now passes the boundary condition through to `dip::GaussFT()`.
80+
See [issue #159](https://github.com/DIPlib/diplib/issues/159).
81+
82+
- The versions of `dip::IsodataThreshold()`, `dip::OtsuThreshold()`, `dip::MinimumErrorThreshold()`,
83+
`dip::GaussianMixtureModelThreshold()`, `dip::TriangleThreshold()` and `dip::BackgroundThreshold()` that take an
84+
image as input, now compute the histogram using the new `dip::Histogram::OptimalConfiguration()` configuration.
85+
This generally makes them more precise. In some cases, the previous behavior was not correct.
86+
See [issue #161](https://github.com/DIPlib/diplib/issues/161).
87+
To reproduce the previous behavior, compute a histogram with default configuration (`dip::Histogram(image)`),
88+
and pass this histogram to the equivalent threshold estimation function. This function will return a threshold
89+
value that can be applied to the image using the comparison operator (`image > threshold`).
90+
91+
- `dip::EstimateNoiseVariance()` uses a potentially more precise threshold internally to exclude edges.
92+
93+
- Made more consistent use of `dip::LabelType`, and we're no longer accepting any label (or object ID) with a value
94+
that doesn't fit in that type. *DIPlib* has always produced labeled images of this type, but it accepts any
95+
unsigned integer image as a label image. Both internally and in the API, sometimes we used `dip::LabelType`
96+
(32-bit unsigned integer), and sometimes we used `dip::uint` (system-dependent size integer, usually 64-bit).
97+
We now consistently use `dip::LabelType` everywhere:
98+
99+
- If the input labeled image is of type `uint64`, any pixel value outside the `dip::LabelType` range will cause
100+
an exception to the thrown. This is true for the measurement functionality and the functions in `regions.h`.
101+
102+
- Added a version of `dip::Measurement::SetObjectIDs()` that takes a `std::vector< dip::LabelType >` as input.
103+
104+
- `dip::ListObjectLabels()` is identical to `dip::GetObjectLabels()` (which is now deprecated), but it returns a
105+
`std::vector< dip::LabelType >` instead of a `dip::UnsignedArray`. `dip::GetObjectLabels()` is deprecated.
106+
107+
- Added `dip::CastLabelType()`, which can be called with any unsigned integer as input, and the same value
108+
as a `dip::LabelType`. If the value is too large to fit in that type, an exception is thrown.
109+
110+
- `dip::GetLabelBoundingBox()` with a `dip::uint` for the `objectID` parameter is deprecated,
111+
it now needs to be a `dip::LabelType`.
112+
113+
- `dip::GetImageChainCodes()` with a `dip::UnsignedArray` for the `objectIDs` parameter is deprecated,
114+
it now needs to be a `std::vector< dip::LabelType >`.
115+
116+
- `dip::ChainCode::objectID` is now of type `dip::LabelType`, was `dip::uint`.
117+
118+
- The measurement functions and data structures still use `dip::uint` for object IDs.
119+
120+
- `dip::ListObjectLabels()` adds an option to list only labels touching the image edge.
121+
122+
- `dip::EdgeObjectsRemove()` also works for labeled images.
123+
124+
- `dip::Image::View::Copy()` with an image as input now allows a 1-pixel input to be used. This behaves like
125+
`dip::Image::View::Fill()` with a `dip::Image::Pixel` as input.
126+
127+
### Bug fixes
128+
129+
- `dip::PairCorrelation`, `dip::ProbabilisticPairCorrelation`, `dip::Semivariogram`, and `dip::ChordLength`
130+
did not properly compute step sizes for `"grid"` sampling, effectively ignoring the value of `probes`
131+
and using all pixels (as if `probes` were set to 0).
132+
133+
- Tensor indexing did not remove color space information as expected (bug introduced with the fix to the move
134+
constructor in 3.4.3).
135+
136+
- `dip::Image::CheckIsMask()` didn't properly check for singleton-expandable masks, accepting masks of any size.
137+
138+
- `dip::FourierTransform()` threw an exception when the real-to-complex dimension had a size of 2.
139+
See [issue #158](https://github.com/DIPlib/diplib/issues/158).
140+
141+
- A wrong assertion in internal code for `dip::FourierTransform()` made it impossible to inverse transform
142+
a real-valued image under certain conditions, when *DIPlib* was built with assertions enabled (bug introduced
143+
with the refactoring of the Fourier code in 3.4.0).
144+
145+
- The 2D parabola fitting function used in `dip::SubpixelLocation()`, `dip::SubpixelMaxima()` and
146+
`dip::SubpixelMinima()`, with the `"parabolic"` and `"gaussian"` methods, was using wrong weights,
147+
making the result not precise. The 3D case was not affected. The faster `"parabolic separable"` and
148+
`"gaussian separable"` methods were also not affected.
149+
150+
### Updated dependencies
151+
152+
- Updated included header-only library *robin-map* to version 1.3.0. Assorted minor improvements.
153+
154+
- Updated included header-only library *pcg-cpp* to the current master branch (last updated 2022-04-08).
155+
Assorted minor improvements.
156+
157+
- Updated bundled *pybind11* to version 2.12.0.
158+
159+
- Updated bundled library *PocketFFT* to the current master branch (last updated 2024-03-22).
160+
This fixes a potential compilation problem on macOS.
161+
162+
### Build changes
163+
164+
- Minimum required version of *CMake* is now 3.12.
165+
166+
167+
168+
169+
## Changes to *DIPimage*
170+
171+
### Changed functionality
172+
173+
- Added `'optimal'` to `diphist`, `diphist2` and `mdhistogram` as an option to choose an optimal bin size.
174+
175+
(See also changes to *DIPlib*.)
176+
177+
### Bug fixes
178+
179+
None, but see bugfixes to *DIPlib*.
180+
181+
### Build and installation changes
182+
183+
- Added the *CMake* option `DIP_JAVA_VERSION`, which can be important when building *DIPimage* for older versions
184+
of MATLAB. The Java version must be equal or older than the version used by MATLAB. Running `version -java`
185+
in MATLAB will tell you what version of Java it is using.
186+
187+
- Added the function `download_bioformats`, which does the same thing as `python -m diplib download_bioformats` in
188+
*PyDIP*. This significantly simplifies the installation instructions for *Bio-Formats*.
189+
190+
191+
192+
193+
## Changes to *PyDIP*
194+
195+
### New functionality
196+
197+
- Added bindings to `dip::GaussFIR()`, to complement `GaussIIR()` and `GaussFT()`. Though it is expected users will
198+
keep using `dip.Gauss()` to access these various algorithms.
199+
200+
- Added bindings for `dip.Units.HasSameDimensions`, `dip.Units.IsDimensionless`, `dip.Units.IsPhysical`,
201+
`dip.Units.AdjustThousands`, `dip.Units.Thousands`.
202+
203+
- Added `dip.Measurement.ToDataFrame()`, which converts the measurement results into a Pandas DataFrame.
204+
This function will import NumPy and Pandas when used, these packages need to be installed.
205+
206+
- Added `dip.Measurement.MeasurementFeature.Subset()` (binding for `dip::Measurement::IteratorFeature::Subset()`)
207+
and `dip.Measurement.FeatureValuesView()`.
208+
209+
- Added bindings for `dip.ColorSpaceManager.SetWhitePoint()`, as well as `dip.ColorSpaceManager.IlluminantA`,
210+
`IlluminantD50`, `IlluminantD55`, `IlluminantD65` and `IlluminantE`.
211+
212+
- Added bindings for `dip.SeparableConvolution()`, `dip.SeparateFilter()` and the `dip.OneDimensionalFilter`
213+
struct.
214+
215+
### Changed functionality
216+
217+
- The *DIPlib* exception classes are now properly bound. This changes the type of the exceptions raised by
218+
the library in Python: `dip.Error` is the new base class, raised exceptions are either `dip.ParameterError`,
219+
`dip.RunTimeError` or `dip.AssertionError`. `dip.Error` is derived from `Exception`.
220+
221+
- Made `diplib.PyDIPjavaio` more easily available as `diplib.javaio`. The new name matches the C++ library
222+
namespace, and when imported properly loads the JVM before importing *PyDIPjavaio*. One can now:
223+
```python
224+
import diplib as dip
225+
import diplib.javaio
226+
image = dip.javaio.ImageReadJavaIO("foo")
227+
```
228+
`dip.ImageRead()` still automatically loads *PyDIPjavaio* on first use.
229+
230+
- `diplib.viewer` is no longer an alias, but a true submodule, like we did for `diplib.javaio`. This should
231+
not change anything for the user, other than some IDEs having less trouble identifying the name.
232+
233+
- `dip.ImageRead()` and `dip.javaio.ImageReadJavaIO()` now also have a version that takes the output image
234+
as a keyword-only argument `out`.
235+
236+
- All the functions named `dip.ImageRead...()` that have a keyword-only argument `out` now return the
237+
`dip::FileInformation` structure (as a dict, just like `dip.ImageRead...Info()` does).
238+
239+
- Unitless `dip.Units` now test false.
240+
241+
- Moved `dip.MeasurementTool.MeasurementFeature` to `dip.Measurement.MeasurementFeature` and
242+
`dip.MeasurementTool.MeasurementObject` to `dip.Measurement.MeasurementObject`.
243+
They are the bindings to `dip::Measurement::IteratorFeature` and `dip::Measurement::IteratorObject` respectively.
244+
245+
(See also changes to *DIPlib*.)
246+
247+
### Bug fixes
248+
249+
- `dip.viewer.Show()` would cause Python to crash if given a raw image.
250+
251+
(See also bugfixes to *DIPlib*.)
252+
253+
### Updated dependencies
254+
255+
- Updated bundled *pybind11* to version 2.12.0.
256+
257+
### Build and installation changes
258+
259+
- The *CMake* option `PYTHON_EXECUTABLE` is no longer used, set `Python_EXECUTABLE` instead. The build script
260+
will, for the time being, copy the value of the former to the latter if the former is set but the latter isn't.
261+
262+
- The *CMake* option `PYBIND11_PYTHON_VERSION` is no longer used. It was mentioned in the documentation, but
263+
probably never really worked.
264+
265+
- Significantly improved the command to download *Bio-Formats*: `python -m diplib download_bioformats` now
266+
has an optional argument `-u` to force an update of the existing library, and another one to specify
267+
which verison to download. By default, it downloads whatever the latest version is, we no longer hard-code
268+
a specific version number.
269+
270+
271+
272+
273+
## Changes to *DIPviewer*
274+
275+
### Bug fixes
276+
277+
- Trying to display an image with wrong color space information would throw an exception. The image is now seen
278+
as a generic tensor image.
279+
280+
- Continuous scrolling devices were way too sensitive when using GLFW, it was really hard to zoom in and out
281+
of an image. (The fix works at least on macOS, let us know if this produces issues on other platforms.)
282+
283+
284+
285+
286+
## Changes to *DIPjavaio*
287+
288+
### Changed functionality
289+
290+
- `dip::javaio::ImageReadJavaIO()` has an additional parameter `imageNumber` to select which image in a multi-image
291+
file to read. The `dip::FileInformation` structure returned now correctly indicates how many images are in the file
292+
in the `numberOfImages` element.

0 commit comments

Comments
 (0)