Skip to content

BUG: Fix image_from_array shape handling for F-contiguous arrays#5775

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-itk-image-from-array-issue
Draft

BUG: Fix image_from_array shape handling for F-contiguous arrays#5775
Copilot wants to merge 2 commits intomainfrom
copilot/fix-itk-image-from-array-issue

Conversation

Copy link
Contributor

Copilot AI commented Feb 6, 2026

Description

itk.image_from_array() incorrectly preserved the original array shape when given F-contiguous inputs (e.g., array.T), while itk.image_view_from_array() correctly used the transposed shape. This inconsistency broke user expectations and made the two functions behave differently for the same input.

Root cause: Double reversal in shape handling

  • Python code unconditionally reversed shape: ndarr.shape[::-1]
  • C++ code reversed again for F-contiguous buffers
  • Net effect: original shape preserved instead of transposed

Fix: Conditional shape reversal based on contiguity

  • C-contiguous: reverse in Python (C++ expects ITK order)
  • F-contiguous: pass as-is (C++ handles reversal)

This matches the existing vector image logic and aligns both functions.

Changes

  • Modules/Bridge/NumPy/wrapping/PyBuffer.i.in: Added contiguity check before shape reversal in GetImageViewFromArray()
  • Wrapping/Generators/Python/Tests/extras.py: Added tests for transposed array handling

Example

import itk
import numpy as np

array = np.empty((1, 2, 3))

# Before fix:
itk.image_from_array(array.T).shape    # (1, 2, 3) - WRONG
itk.image_view_from_array(array.T).shape  # (3, 2, 1) - correct

# After fix:
itk.image_from_array(array.T).shape    # (3, 2, 1) - correct
itk.image_view_from_array(array.T).shape  # (3, 2, 1) - correct

PR Checklist

  • No API changes were made (or the changes have been approved)
  • No major design changes were made (or the changes have been approved)
  • Added test (or behavior not changed)
  • Updated API documentation (or API not changed)
  • Added license to new files (if any)
  • Added Python wrapping to new files (if any) as described in ITK Software Guide Section 9.5
  • Added ITK examples for all new major features (if any)
Original prompt

This section details on the original issue you should resolve

<issue_title>Unexpected behavior of itk.image_from_array when passing array.T</issue_title>
<issue_description>

Hi, and thanks again for making ITK!

Description

The shape of an image created with itk.image_from_array is unexpected when the input is not a contiguous array. I discovered this when passing array.T and was surprised when the shape was the same as for array. The issue doesn't happen with itk. image_view_from_array.

Steps to Reproduce

import itk
import numpy as np

array = np.empty((1, 2, 3))

print(f"{array.shape = }")
print()
print(f"{itk.image_from_array(array).shape = }")
print(f"{itk.image_from_array(array.T).shape = }")
print(f"{itk.image_from_array(array.T.copy()).shape = }")
print()
print(f"{itk.image_view_from_array(array).shape = }")
print(f"{itk.image_view_from_array(array.T).shape = }")
print(f"{itk.image_view_from_array(array.T.copy()).shape = }")
print()
print(f"{array.flags['C_CONTIGUOUS'] = }")
print(f"{array.T.flags['C_CONTIGUOUS'] = }")
print(f"{array.T.copy().flags['C_CONTIGUOUS'] = }")
print()
print(f"{array.flags['F_CONTIGUOUS'] = }")
print(f"{array.T.flags['F_CONTIGUOUS'] = }")
print(f"{array.T.copy().flags['F_CONTIGUOUS'] = }")

Expected behavior

I expected reversed shapes for itk.image_from_array(array) and itk.image_from_array(array.T).

Actual behavior (output of script above)

array.shape = (1, 2, 3)

itk.image_from_array(array).shape = (1, 2, 3)
itk.image_from_array(array.T).shape = (1, 2, 3)  # I expected (3, 2, 1) here!
itk.image_from_array(array.T.copy()).shape = (3, 2, 1)

itk.image_view_from_array(array).shape = (1, 2, 3)
itk.image_view_from_array(array.T).shape = (3, 2, 1)
itk.image_view_from_array(array.T.copy()).shape = (3, 2, 1)

array.flags['C_CONTIGUOUS'] = True
array.T.flags['C_CONTIGUOUS'] = False
array.T.copy().flags['C_CONTIGUOUS'] = True

array.flags['F_CONTIGUOUS'] = False
array.T.flags['F_CONTIGUOUS'] = True
array.T.copy().flags['F_CONTIGUOUS'] = False

Reproducibility

Always.

Versions

$ python -c "import numpy; print(numpy.__version__)"
1.26.2

$ python -c "import itk; print(itk.Version.GetITKVersion())"
5.3.0

Environment

$ python <(curl -s https://raw.githubusercontent.com/fepegar/torchio/main/print_system.py)
Platform:   macOS-14.0-arm64-arm-64bit
[...]
Python:     3.11.5 (main, Sep 11 2023, 08:31:25) [Clang 14.0.6 ]

</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

The issue was that GetImageViewFromArray always reversed the shape for
non-vector images, regardless of whether the array was C-contiguous or
F-contiguous. However, the C++ code reverses the shape again for F-contiguous
arrays, resulting in a double reversal.

The fix: Only reverse the shape in Python for C-contiguous arrays. For
F-contiguous arrays, pass the shape as-is to C++, which will handle the
reversal there.

Added comprehensive test cases for both image_from_array and
image_view_from_array with transposed arrays.

Co-authored-by: thewtex <25432+thewtex@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix unexpected behavior of itk.image_from_array with array.T BUG: Fix image_from_array shape handling for F-contiguous arrays Feb 6, 2026
Copilot AI requested a review from thewtex February 6, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unexpected behavior of itk.image_from_array when passing array.T

2 participants