diff --git a/Wrapping/Generators/Python/Tests/extras.py b/Wrapping/Generators/Python/Tests/extras.py index 00cdc475661..4042337c49c 100644 --- a/Wrapping/Generators/Python/Tests/extras.py +++ b/Wrapping/Generators/Python/Tests/extras.py @@ -789,6 +789,22 @@ def assert_images_equal(base, test): itk_image = itk.image_from_vtk_image(vtk_image) assert_images_equal(input_image, itk_image) + # A 2D scalar image must round-trip back to 2D, not grow a spurious + # z dimension of size 1 (VTK images are always stored with 3 dimensions). + image = itk.image_from_array(np.random.rand(8, 12).astype(np.float32)) + vtk_image = itk.vtk_image_from_image(image) + image_round = itk.image_from_vtk_image(vtk_image) + assert image_round.GetImageDimension() == 2 + assert_images_equal(image, image_round) + + # A 3D scalar image with a single slice must stay 3D, not be mistaken + # for a padded 2D image. + image = itk.image_from_array(np.random.rand(1, 8, 12).astype(np.float32)) + vtk_image = itk.vtk_image_from_image(image) + image_round = itk.image_from_vtk_image(vtk_image) + assert image_round.GetImageDimension() == 3 + assert_images_equal(image, image_round) + except ImportError: print("vtk not imported. Skipping vtk conversion tests") pass diff --git a/Wrapping/Generators/Python/itk/support/extras.py b/Wrapping/Generators/Python/itk/support/extras.py index ffb7c4798e6..d344eb163c3 100644 --- a/Wrapping/Generators/Python/itk/support/extras.py +++ b/Wrapping/Generators/Python/itk/support/extras.py @@ -709,6 +709,12 @@ def vtk_image_from_image(l_image: itkt.ImageOrImageSource) -> vtk.vtkImageData: dims = [1] * 3 dims[:dim] = itk.size(l_image) vtk_image.SetDimensions(dims) + # Record the original dimension: a padded 2D->3D image and a genuine + # single-slice 3D image both have dims[-1] == 1, so this disambiguates + # them for image_from_vtk_image. + dim_array = numpy_to_vtk(np.array([dim], dtype=np.int32)) + dim_array.SetName("ITKOriginalDimension") + vtk_image.GetFieldData().AddArray(dim_array) # Copy direction matrix for VTK>=9 import vtk @@ -753,8 +759,15 @@ def image_from_vtk_image(vtk_image: vtk.vtkImageData) -> itkt.ImageBase: number_of_components = point_data.GetScalars().GetNumberOfComponents() is_vector = number_of_components != 1 dims = list(vtk_image.GetDimensions()) - if is_vector and dims[-1] == 1: - dims = dims[:-1] # 2D, not 3D + original_dimension_array = vtk_image.GetFieldData().GetArray("ITKOriginalDimension") + if original_dimension_array is not None: + # From vtk_image_from_image: authoritative. + original_dimension = int(vtk_to_numpy(original_dimension_array)[0]) + if original_dimension == 2 and dims[-1] == 1: + dims = dims[:-1] + elif is_vector and dims[-1] == 1: + # No metadata: same best-effort guess as before. + dims = dims[:-1] dims.reverse() if is_vector: dims.append(number_of_components)