Complete code that works
import gc
from threading import Thread
import vtk
def create_interactive_window():
# Create a cube
cube = vtk.vtkCubeSource()
# Create a mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(cube.GetOutputPort())
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# Create a renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
renderer.SetBackground(0.1, 0.2, 0.4) # Background color
# Create a render window
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window.SetSize(800, 600)
print("Onscreen render window: ", render_window)
# Create a render window interactor
render_window_interactor = vtk.vtkRenderWindowInteractor()
render_window_interactor.SetRenderWindow(render_window)
# Initialize and start the interaction
render_window.Render()
render_window_interactor.Initialize()
return render_window_interactor
def make_offscreen_renderer():
# Create a cube
cube = vtk.vtkCubeSource()
# Create a mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(cube.GetOutputPort())
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# Create a renderer
renderer = vtk.vtkOpenGLRenderer()
renderer.AddActor(actor)
renderer.SetBackground(0.1, 0.2, 0.4) # Background color
renwin = vtk.vtkRenderWindow()
print("Offscreen render window: ", renwin)
renwin.SetOffScreenRendering(True)
renwin.AddRenderer(renderer)
renwin.SetSize(800, 600)
camera = renderer.GetActiveCamera()
return renwin
if __name__ == '__main__':
#
gc.disable()
interactor = create_interactive_window()
#
#
def produce_offscreen_image():
renwin = make_offscreen_renderer()
renwin.Render()
# Use PIL to display the image (not required, just to check that it works)
#
from PIL import Image
from vtk.util.numpy_support import vtk_to_numpy
import numpy as np
nx, ny = renwin.GetSize()
arr = vtk.vtkUnsignedCharArray()
renwin.GetRGBACharPixelData(0, 0, nx - 1, ny - 1, 0, arr)
narr = vtk_to_numpy(arr).T[:3].T.reshape([ny, nx, 3])
narr = np.flip(narr, axis=0)
pil_img = Image.fromarray(narr)
pil_img.show()
renwin.Finalize() # <--- FIX
whoopsie = [renwin] # <--- create a list with the renwin object
whoopsie.append(whoopsie) # <--- append the list to itself, to create a circular reference
# This means it will not be released because the reference count will never reach 0
new_thread = Thread(
target=lambda: produce_offscreen_image()
)
new_thread.start()
new_thread.join()
#
print("COLLECT")
gc.collect(2)
interactor.Start()