From 3af71109863765fc8677fe850e8b53f38d470bab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:57:37 -0500 Subject: [PATCH] BUG: Fix image_from_array to handle non-contiguous arrays GetImageViewFromArray always reversed the shape for non-vector images, regardless of array memory layout. The C++ code reverses the shape again for F-contiguous arrays, resulting in a double reversal. Only reverse the shape in Python for C-contiguous arrays. For F-contiguous arrays, pass the shape as-is to C++ which handles the reversal. Co-authored-by: Matthew McCormick --- Modules/Bridge/NumPy/wrapping/PyBuffer.i.in | 5 ++++- Wrapping/Generators/Python/Tests/extras.py | 23 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in b/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in index 22a95428726..61e725179c4 100644 --- a/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in +++ b/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in @@ -103,7 +103,10 @@ else: imgview = itkPyBuffer@PyBufferTypes@._get_image_view_from_contiguous_array(ndarr, ndarr.shape[-1:0:-1], ndarr.shape[0]) else: - imgview = itkPyBuffer@PyBufferTypes@._get_image_view_from_contiguous_array(ndarr, ndarr.shape[::-1], 1) + if ndarr.flags['C_CONTIGUOUS']: + imgview = itkPyBuffer@PyBufferTypes@._get_image_view_from_contiguous_array(ndarr, ndarr.shape[::-1], 1) + else: + imgview = itkPyBuffer@PyBufferTypes@._get_image_view_from_contiguous_array(ndarr, ndarr.shape, 1) # Keep a reference imgview._SetBase(ndarr) diff --git a/Wrapping/Generators/Python/Tests/extras.py b/Wrapping/Generators/Python/Tests/extras.py index c0601e5ef2d..0638f862233 100644 --- a/Wrapping/Generators/Python/Tests/extras.py +++ b/Wrapping/Generators/Python/Tests/extras.py @@ -418,6 +418,29 @@ def custom_callback(name, progress): arr_fortran = arr.copy(order="F") image = itk.GetImageViewFromArray(arr_fortran) assert np.array_equal(arr_fortran.shape, image.shape) +# Test that image_from_array handles array.T correctly (F-contiguous arrays) +test_arr = np.empty((1, 2, 3)) +image_from_arr = itk.image_from_array(test_arr) +image_from_transpose = itk.image_from_array(test_arr.T) +image_from_transpose_copy = itk.image_from_array(test_arr.T.copy()) +assert np.array_equal( + image_from_arr.shape, test_arr.shape +), f"Expected shape {test_arr.shape}, got {image_from_arr.shape}" +assert np.array_equal( + image_from_transpose.shape, test_arr.T.shape +), f"Expected shape {test_arr.T.shape}, got {image_from_transpose.shape}" +assert np.array_equal( + image_from_transpose_copy.shape, test_arr.T.shape +), f"Expected shape {test_arr.T.shape}, got {image_from_transpose_copy.shape}" +# Also verify with image_view_from_array for consistency +image_view_from_arr = itk.image_view_from_array(test_arr) +image_view_from_transpose = itk.image_view_from_array(test_arr.T) +assert np.array_equal( + image_view_from_arr.shape, test_arr.shape +), f"Expected shape {test_arr.shape}, got {image_view_from_arr.shape}" +assert np.array_equal( + image_view_from_transpose.shape, test_arr.T.shape +), f"Expected shape {test_arr.T.shape}, got {image_view_from_transpose.shape}" image = itk.image_from_array(arr, is_vector=True) assert image.GetImageDimension() == 2 image = itk.GetImageViewFromArray(arr, is_vector=True)