ENH: Implement PEP 688 buffer protocol for ITK Python
Description
Implements PEP 688 buffer protocol support for ITK Images and ImportImageContainers, enabling zero-copy NumPy interoperability in Python 3.12+. Based on #5665 by @blowekamp with fixes for test failures and implementation refinements.
Key changes:
-
C++ infrastructure: Added
PyBuffer::_GetMemoryViewFromImportImageContainer()with overflow checking -
Python
__buffer__()methods: Implemented forImageandImportImageContainerclasses- Reuses existing
PyBuffer._GetArrayViewFromImage() - Extracts component types for composite pixels (RGB, Vector, etc.)
- Handles shape conversion to NumPy C-order (channels-last)
- Fallback
_get_formatstring()for robustness
- Reuses existing
-
Build system: Wrapping for
ImportImageContainer, CMake macro application -
Backward compatibility:
__array__()uses buffer protocol for Python 3.12+, falls back toarray_from_image()otherwise
Usage:
import itk
import numpy as np
image = itk.Image[itk.UC, 2].New()
image.SetRegions([100, 100])
image.Allocate()
# Python 3.12+: zero-copy conversion via buffer protocol
array = np.asarray(image) # Direct memory access
# Multi-component images follow channels-last convention
rgb_image = itk.Image[itk.RGBPixel[itk.UC], 2].New()
rgb_array = np.asarray(rgb_image) # Shape: [height, width, 3]
PR Checklist
- [x] No API changes were made (or the changes have been approved)
- [x] No major design changes were made (or the changes have been approved)
- [x] Added test (or behavior not changed)
- [x] Updated API documentation (or API not changed)
- [x] Added license to new files (if any)
- [x] 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)
Related:
- Original PR: #5665
- PEP 688: https://peps.python.org/pep-0688/
- SimpleITK implementation: SimpleITK/SimpleITK#2447
Co-authored-by: Bradley Lowekamp [email protected]
Original prompt
Take ITK PR #5665 and push it forward in a new PR that you cerate, addressing failing tests and refine the implementation and tests as appropriate.
We are currently getting test failures:
mac
itkImagePythonTest
Traceback (most recent call last): File "/Users/runner/work/1/s/Modules/Core/Common/wrapping/test/itkImageTest.py", line 37, in
array = np.array(image.buffer()) File "/Users/runner/work/1/s-build/Wrapping/Generators/Python/itk/itkImagePython.py", line 27853, in buffer memview = memoryview(self.GetPixelContainer()) TypeError: memoryview: a bytes-like object is required, not 'SwigPyObject' itkTestDriver: Process exited with return value: 1 itkTransformSerializationTest
Traceback (most recent call last): File "/Users/runner/work/1/s/Modules/Core/Transform/wrapping/test/itkTransformSerializationTest.py", line 167, in
assert np.array_equal(np.array(resampled_image1), np.array(resampled_image2)) AssertionError PyImageFilterTest
Traceback (most recent call last): File "/Users/runner/work/1/s/Wrapping/Generators/Python/Tests/PyImageFilterTest.py", line 47, in
assert np.all(np.asarray(output_image) == 42) AssertionError itkTestDriver: Process exited with return value: 1 PythonExtrasTest
Traceback (most recent call last): File "/Users/runner/work/1/s/Wrapping/Generators/Python/Tests/extras.py", line 176, in
assert np.sum(comparison) == 0.0 AssertionError And similar test failures on Linux.
See also:
- https://peps.python.org/pep-0688/
- @SimpleITK/SimpleITK/pull/2447
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.