vtk9 vtkLookupTable transparency

I’m trying to take a screenshot (vtkWindowToImageFilter) of a 4x4 toy image with a vtkLookupTable that transform NaN values into transparent values. Here’s my code:

import numpy as np
import vtk
data = np.array(
    [
        [0.0, 20.0, 0.5, 10.0],
        [10.0, 0.0, 10.5, 0.5],
        [0.5, 10.5, 0.0, 10.0],
        [10.0, 0.5, 20.0, np.NAN],
    ],
    dtype="float32",
)

data_importer = vtk.vtkImageImport()
data_str = data.tobytes()
data_importer.CopyImportVoidPointer(data_str, len(data_str))
data_importer.SetDataScalarTypeToFloat()
data_importer.SetNumberOfScalarComponents(1)
data_importer.SetDataSpacing(1.0, 1.0, 0.0)
data_importer.SetDataOrigin(0.5, 0.5, 0.5)
data_importer.SetWholeExtent(0, data.shape[1] - 1, 0, data.shape[0] - 1, 0, 0)
data_importer.SetDataExtentToWholeExtent()
data_importer.Update()

lut = vtk.vtkLookupTable()
lut.SetRange(0.0, 20.0)
lut.SetNanColor(1.0, 0.0, 0.0, 0.0)
lut.SetRampToLinear()
lut.SetHueRange(0.0, 0.0)
lut.SetSaturationRange(0.0, 0.0)
lut.SetValueRange(0.0, 1.0)

color = vtk.vtkImageMapToColors()
color.SetLookupTable(lut)
color.SetOutputFormatToRGB()
color.SetInputConnection(data_importer.GetOutputPort())

actor = vtk.vtkImageActor()
actor.SetInterpolate(False)
actor.GetMapper().SetInputConnection(color.GetOutputPort())
actor.GetMapper().BorderOn()
actor.GetProperty().SetOpacity(1.0)

renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
renderer.ResetCamera()
renderer.SetBackground(1.0, 0.0, 0.0)

render_window = vtk.vtkRenderWindow()
render_window.SetSize(800, 600)
render_window.AddRenderer(renderer)
render_window.SetAlphaBitPlanes(1)

w2if = vtk.vtkWindowToImageFilter()
w2if.SetInput(render_window)
w2if.SetInputBufferTypeToRGBA()
w2if.Update()

writer = vtk.vtkPNGWriter()
writer.SetFileName("test.png")
writer.SetInputData(w2if.GetOutput())
writer.Write()

This was working perfectly on v8.1.2. Both the background and the NaN pixel were transparent. In order to work, I had to use color.SetOutputFormatToRGBA().

On v9.2.2 however, the NaN pixel gets a different treatment, wathever method I use.

  • If I use SetOutputFormatToRGBA, the whole image is transparent.
  • If I use SetOutputFormatToRGB, I get the image below

The problem is not with vtkLookupTable or with vtkImageMapToColors. This is easy to demonstrate by making two small adjustments to the code:

color.SetOutputFormatToRGBA()

and

writer.SetInputConnection(color.GetOutputPort())

Those changes (i.e. writing the output directly from vtkImageMapToColors) will give you an image where the upper right square is transparent.

Also, the image is rendered properly on the screen (which can be seen by adding an interactor to the end of your example):

iren = vtk.vtkRenderWindowInteractor()
render_window.SetInteractor(iren)
iren.Initialize()
iren.Start()

Of course, on the screen we can’t actually see what is in the render window’s alpha component. We can set renderer.SetBackgroundAlpha(0.0) or renderer.SetBackgroundAlpha(1.0) and the on-screen rendering will look the same for both.

So that’s as far as I’ve been able to diagnose the issue. Either there has been a change with the way vtkRenderer handles the window’s alpha component, or there has been a change in the way vtkWindowToImageFilter handles the window’s alpha component.

If I had to guess, I’d say that vtkWindowToImageFilter is the most likely culprit.

What operating system and GPU are you using?

One further question. If you still have vtk 8.1.2 installed, what does it give for type(renderer)?
This is just to check whether you were using the new “OpenGL2” backend or the new “OpenGL” backend, since VTK 8 supported both.
Nevermind, I checked and the regression is unrelated to OpenGL2 vs OpenGL backend.

Hi David,

You’re right. When I apply your suggestions, I can see that the upper right pixel is rendered correctly when I use the vtkRenderWindowInteractor. The png however is all transparent, as it was before.

Can I do something else to help you? I could test the other vtk versions (all 9.x.y) available on pip to see if it broke between 9.0.0 and 9.2.2.

I’m using Ubuntu 20.04.5 LTS with a GeForce GTX 1650 Ti.

Thanks. It would be very useful to know whether it was 9.0, 9.1, or 9.2 that introduced the regression.

Pinning it down to a specific commit will probably require git-bisect (which, if you’re not familiar with it, is a divide-and-conquer search for problem which requires repeatedly building and VTK for different commits and testing for the specific regression).

Well, there wasn’t much to test. The first available version on Linux is 9.0.1 and it’s already broken. I tested 9.0.0 on a Window machine and it’s also broken. The regression was introduced between ]8.1.2 and 9.0.0[.

I’ll try testing 8.2.0 later, then start a bisect depending on the result.