I’m developing a 2D image viewer in VTK.js (using vtkImageSlice + vtkImageMapper) and I’d like to provide an interactive window/level (intensity range) editor.
With given LUT/CTF I’d like to achieve:
-
Let the user adjust the window min/max interactively,
-
Possibly choose a mapping function (e.g. linear or sigmoid),
-
And visualize how the LUT/CTF applies across that range.
What I’ve tried
I’ve been experimenting with the vtkPiecewiseGaussianWidget, since it provides a histogram and looks like a good starting point.
const widget = vtkPiecewiseGaussianWidget.newInstance({
numberOfBins: 256,
size: [400, 150],
});
widget.setContainer(widgetContainer);
widget.setColorTransferFunction(ctf);
widget.setDataArray(imageData);
widget.bindMouseListeners();
However, I’m confused about a few points:
-
What is the purpose of
setColorTransferFunction()?- I’m not sure whether the CTF is displayed or actually used for something internally.
-
How is the range determined or shown?
-
I don’t see any numeric labels or clear indication of the scalar range in the widget.
-
It’s unclear how the widget’s histogram aligns with the image’s data range (e.g. when calling
setDataArray(imageData, { min, max })).
-
-
Is the widget intended only for opacity editing?
- The interface seems to focus on Gaussian peaks (opacity control), which makes sense for volume rendering — but I’m not sure whether it’s suitable or adaptable for 2D window/level control.
What I’d like to ask
-
Is there any existing widget or recommended approach in VTK.js for window/level or CTF editing in 2D images?
-
Could the
vtkPiecewiseGaussianWidgetbe adapted to this purpose — e.g., to allow moving markers for min/max window or to manipulate the color transfer function directly? -
Is there any documentation or example explaining how the widget’s data range, histogram, and color mapping work internally?
I was expecting that the following hook will automatically adjust at least range of CTF based on user input but it does nothing
widget.onOpacityChange(() => {
renderWindow.render();
});