diff --git a/Wrapping/Common/mitk_swig_cpp_include.i b/Wrapping/Common/mitk_swig_cpp_include.i index fc7392dd82..62b980cc64 100644 --- a/Wrapping/Common/mitk_swig_cpp_include.i +++ b/Wrapping/Common/mitk_swig_cpp_include.i @@ -1,61 +1,96 @@ %{ #include #include #include #include #include #include #include // SWIG Doesn't wrap namespaces. This leads to some problems, if the namespaces are not used. using namespace mitk; using namespace itk; std::vector GetImageSize(mitk::Image::Pointer image) { std::vector< unsigned int > size; unsigned int dimension = image->GetDimension(); for (int i = 0; i < dimension; ++i) { size.push_back(image->GetDimension(i)); } return size; } std::vector GetImageSize(mitk::Image* image) { std::vector< unsigned int > size; unsigned int dimension = image->GetDimension(); for (int i = 0; i < dimension; ++i) { size.push_back(image->GetDimension(i)); } return size; } struct TypeDefinitions { static const int ComponentTypeUInt8 = MapPixelType::value>::IOComponentType; static const int ComponentTypeInt8 = MapPixelType::value>::IOComponentType; static const int ComponentTypeUInt16 = MapPixelType::value>::IOComponentType; static const int ComponentTypeInt16 = MapPixelType::value>::IOComponentType; static const int ComponentTypeUInt32 = MapPixelType::value>::IOComponentType; static const int ComponentTypeInt32 = MapPixelType::value>::IOComponentType; static const int ComponentTypeFloat = MapPixelType::value>::IOComponentType; static const int ComponentTypeDouble = MapPixelType::value>::IOComponentType; }; + +mitk::PixelType MakePixelTypeFromTypeID(int componentTypeID, int numberOfComponents) +{ + switch (componentTypeID) + { + case TypeDefinitions::ComponentTypeUInt8 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeInt8 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeUInt16 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeInt16 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeUInt32 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeInt32 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeFloat : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeDouble : + return mitk::MakePixelType(numberOfComponents); + default: + return mitk::MakePixelType(numberOfComponents); + } +} + +mitk::Image::Pointer MakeImage(mitk::PixelType pixelType, std::vector shape) +{ + mitk::Image::Pointer image = mitk::Image::New(); + image->Initialize(pixelType, shape.size(), shape.data()); + return image; +} + %} std::vector GetImageSize(mitk::Image::Pointer image); std::vector GetImageSize(mitk::Image* image); +mitk::PixelType MakePixelTypeFromTypeID(int componentTypeID, int numberOfComponents); +mitk::Image::Pointer MakeImage(mitk::PixelType pixelType, std::vector shape); %constant int ComponentTypeUInt8 = TypeDefinitions::ComponentTypeUInt8; %constant int ComponentTypeInt8 = TypeDefinitions::ComponentTypeInt8; %constant int ComponentTypeUInt16 = TypeDefinitions::ComponentTypeUInt16; %constant int ComponentTypeInt16 = TypeDefinitions::ComponentTypeInt16; %constant int ComponentTypeUInt32 = TypeDefinitions::ComponentTypeUInt32; %constant int ComponentTypeInt32 = TypeDefinitions::ComponentTypeInt32; %constant int ComponentTypeFloat = TypeDefinitions::ComponentTypeFloat; %constant int ComponentTypeDouble = TypeDefinitions::ComponentTypeDouble; \ No newline at end of file diff --git a/Wrapping/Python/MITK.i b/Wrapping/Python/MITK.i index da1ce31ea8..e76d304b0b 100644 --- a/Wrapping/Python/MITK.i +++ b/Wrapping/Python/MITK.i @@ -1,135 +1,165 @@ %module PythonMITK %include %{ #include "mitkNumpyArrayConversion.cxx" %} // Numpy array conversion support %native(_GetMemoryViewFromImage) PyObject *mitk_GetMemoryViewFromImage( PyObject *self, PyObject *args ); +%native(_SetImageFromArray) PyObject *mitk_SetImageFromArray( PyObject *(self), PyObject *args ); %pythoncode %{ HAVE_NUMPY = True try: import numpy except ImportError: HAVE_NUMPY = False def _get_numpy_dtype( mitkImage ): """Given a MITK image, returns the numpy.dtype which describes the data""" if not HAVE_NUMPY: raise ImportError('Numpy not available.') # this is a mapping from MITK's pixel id to numpy's dtype _mitk_np = {ComponentTypeUInt8:numpy.uint8, ComponentTypeUInt16:numpy.uint16, ComponentTypeUInt32:numpy.uint32, ComponentTypeInt8:numpy.int8, ComponentTypeInt16:numpy.int16, ComponentTypeInt32:numpy.int32, ComponentTypeFloat:numpy.float32, ComponentTypeDouble:numpy.float64, } return _mitk_np[ mitkImage.GetPixelType().GetComponentType() ] def _get_mitk_pixelid(numpy_array_type): """Returns a SimpleITK PixelID given a numpy array.""" if not HAVE_NUMPY: raise ImportError('Numpy not available.') # This is a Mapping from numpy array types to sitks pixel types. - _np_mitk = {numpy.character:sitkUInt8, + _np_mitk = {numpy.character:ComponentTypeUInt8, numpy.uint8:ComponentTypeUInt8, numpy.uint16:ComponentTypeUInt16, numpy.uint32:ComponentTypeUInt32, numpy.int8:ComponentTypeInt8, numpy.int16:ComponentTypeInt16, numpy.int32:ComponentTypeInt32, numpy.float32:ComponentTypeFloat, numpy.float64:ComponentTypeDouble, } try: return _np_mitk[numpy_array_type.dtype] except KeyError: for key in _np_mitk: if numpy.issubdtype(numpy_array_type.dtype, key): return _np_mitk[key] raise TypeError('dtype: {0} is not supported.'.format(numpy_array_type.dtype)) def _get_sitk_vector_pixelid(numpy_array_type): """Returns a SimpleITK vecotr PixelID given a numpy array.""" if not HAVE_NUMPY: raise ImportError('Numpy not available.') # This is a Mapping from numpy array types to sitks pixel types. _np_sitk = {numpy.character:sitkVectorUInt8, numpy.uint8:sitkVectorUInt8, numpy.uint16:sitkVectorUInt16, numpy.uint32:sitkVectorUInt32, numpy.uint64:sitkVectorUInt64, numpy.int8:sitkVectorInt8, numpy.int16:sitkVectorInt16, numpy.int32:sitkVectorInt32, numpy.int64:sitkVectorInt64, numpy.float32:sitkVectorFloat32, numpy.float64:sitkVectorFloat64, } try: return _np_sitk[numpy_array_type.dtype] except KeyError: for key in _np_sitk: if numpy.issubdtype(numpy_array_type.dtype, key): return _np_sitk[key] raise TypeError('dtype: {0} is not supported.'.format(numpy_array_type.dtype)) # SimplyITK <-> Numpy Array conversion support. #http://www.nickdarnell.com/swig-casting-revisited/ def GetArrayViewFromImage(image): """Get a NumPy ndarray view of a SimpleITK Image. Returns a Numpy ndarray object as a "view" of the SimpleITK's Image buffer. This reduces pixel buffer copies, but requires that the SimpleITK image object is kept around while the buffer is being used. """ if not HAVE_NUMPY: raise ImportError('NumPy not available.') dtype = _get_numpy_dtype( image ) shape = GetImageSize(image); if image.GetPixelType().GetNumberOfComponents() > 1: shape = ( image.GetPixelType().GetNumberOfComponents(), ) + shape imageMemoryView = _PythonMITK._GetMemoryViewFromImage(image) arrayView = numpy.asarray(imageMemoryView).view(dtype = dtype) arrayView.shape = shape[::-1] return arrayView def GetArrayFromImage(image): """Get a NumPy ndarray from a SimpleITK Image. This is a deep copy of the image buffer and is completely safe and without potential side effects. """ # TODO: If the image is already not unique then a second copy may be made before the numpy copy is done. arrayView = GetArrayViewFromImage(image) # perform deep copy of the image buffer return numpy.array(arrayView, copy=True) +def GetImageFromArray( arr, isVector=False): + """Get a SimpleITK Image from a numpy array. If isVector is True, then a 3D array will be treated as a 2D vector image, otherwise it will be treated as a 3D image""" + + if not HAVE_NUMPY: + raise ImportError('Numpy not available.') + + z = numpy.asarray( arr ) + + assert z.ndim in ( 2, 3, 4 ), \ + "Only arrays of 2, 3 or 4 dimensions are supported." + + id = _get_mitk_pixelid( z ) + #img = Image_New() + + if ( z.ndim == 3 and isVector ) or (z.ndim == 4): + pixelType=MakePixelTypeFromTypeID(id, z.shape[-1]) + newShape=VectorUInt32(z.shape[-2::-1]) + img = MakeImage(pixelType, newShape) + #img.Initialize(pixelType, z.ndim - 1, z.shape[-2::-1]) + elif z.ndim in ( 2, 3 ): + pixelType=MakePixelTypeFromTypeID(id, 1) + newShape=VectorUInt32(z.shape[::-1]) + img = MakeImage(pixelType, newShape) + #img.Initialize(pixelType, z.ndim, z.shape[::-1]) + + _PythonMITK._SetImageFromArray( z.tostring(), img ) + + return img + %} \ No newline at end of file diff --git a/Wrapping/Python/mitkNumpyArrayConversion.cxx b/Wrapping/Python/mitkNumpyArrayConversion.cxx index 1e6228689b..ce45d5e2fd 100644 --- a/Wrapping/Python/mitkNumpyArrayConversion.cxx +++ b/Wrapping/Python/mitkNumpyArrayConversion.cxx @@ -1,288 +1,234 @@ /*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include #include #include #include #include "mitkImage.h" // Python is written in C #ifdef __cplusplus extern "C" { #endif /** An internal function that returns a memoryview object to the * SimpleITK Image's buffer (shallow). The correct copy and writing * policies need to be done by the end-user method. */ static PyObject * mitk_GetMemoryViewFromImage( PyObject *SWIGUNUSEDPARM(self), PyObject *args ) { const void * mitkBufferPtr; Py_ssize_t len; std::vector< unsigned int > size; size_t pixelSize = 1; unsigned int dimension; /* Cast over to a sitk Image. */ PyObject * pyImage; void * voidImage; mitk::Image * mitkImage; int res = 0; PyObject * memoryView = NULL; Py_buffer pyBuffer; memset(&pyBuffer, 0, sizeof(Py_buffer)); if( !PyArg_ParseTuple( args, "O", &pyImage ) ) { SWIG_fail; // SWIG_fail is a macro that says goto: fail (return NULL) } res = SWIG_ConvertPtr( pyImage, &voidImage, SWIGTYPE_p_mitk__Image, 0 ); if (!SWIG_IsOK(res)) { mitk::Image::Pointer tmpImage; res = SWIG_ConvertPtr(pyImage, &voidImage, SWIGTYPE_p_itk__SmartPointerT_mitk__Image_t, 0); if (!SWIG_IsOK(res)) { SWIG_exception_fail(SWIG_ArgError(res), "in method 'GetByteArrayFromImage', argument needs to be of type 'sitk::Image *'"); } tmpImage = *(reinterpret_cast(voidImage)); voidImage = reinterpret_cast(tmpImage.GetPointer()); } mitkImage = reinterpret_cast< mitk::Image * >( voidImage ); mitkBufferPtr = mitkImage->GetData(); pixelSize = mitkImage->GetPixelType().GetBitsPerComponent() / 8; dimension = mitkImage->GetDimension(); for (int i = 0; i < dimension; ++i) { size.push_back(mitkImage->GetDimension(i)); } // if the image is a vector just treat is as another dimension if ( mitkImage->GetPixelType().GetNumberOfComponents() > 1 ) { size.push_back( mitkImage->GetPixelType().GetNumberOfComponents() ); } len = std::accumulate( size.begin(), size.end(), unsigned int(1), std::multiplies() ); len *= pixelSize; if (PyBuffer_FillInfo(&pyBuffer, NULL, (void*)mitkBufferPtr, len, true, PyBUF_CONTIG_RO)!=0) { SWIG_fail; } memoryView = PyMemoryView_FromBuffer(&pyBuffer); PyBuffer_Release(&pyBuffer); return memoryView; fail: Py_XDECREF( memoryView ); return NULL; } -// -///** An internal function that performs a deep copy of the image buffer -// * into a python byte array. The byte array can later be converted -// * into a numpy array with the frombuffer method. -// */ -//static PyObject* -//sitk_SetImageFromArray( PyObject *SWIGUNUSEDPARM(self), PyObject *args ) -//{ -// PyObject * pyImage = NULL; -// -// const void *buffer; -// Py_ssize_t buffer_len; -// Py_buffer pyBuffer; -// memset(&pyBuffer, 0, sizeof(Py_buffer)); -// -// const sitk::Image * sitkImage = NULL; -// void * sitkBufferPtr = NULL; -// size_t pixelSize = 1; -// -// unsigned int dimension = 0; -// std::vector< unsigned int > size; -// size_t len = 1; -// -// // We wish to support both the new PEP3118 buffer interface and the -// // older. So we first try to parse the arguments with the new buffer -// // protocol, then the old. -// if (!PyArg_ParseTuple( args, "s*O", &pyBuffer, &pyImage ) ) -// { -// PyErr_Clear(); -// -//#ifdef PY_SSIZE_T_CLEAN -// typedef Py_ssize_t bufSizeType; -//#else -// typedef int bufSizeType; -//#endif -// -// bufSizeType _len; -// // This function takes 2 arguments from python, the first is an -// // python object which support the old "ReadBuffer" interface -// if( !PyArg_ParseTuple( args, "s#O", &buffer, &_len, &pyImage ) ) -// { -// return NULL; -// } -// buffer_len = _len; -// } -// else -// { -// if ( PyBuffer_IsContiguous( &pyBuffer, 'C' ) != 1 ) -// { -// PyBuffer_Release( &pyBuffer ); -// PyErr_SetString( PyExc_TypeError, "A C Contiguous buffer object is required." ); -// return NULL; -// } -// buffer_len = pyBuffer.len; -// buffer = pyBuffer.buf; -// } -// -// /* Cast over to a sitk Image. */ -// { -// void * voidImage; -// int res = 0; -// res = SWIG_ConvertPtr( pyImage, &voidImage, SWIGTYPE_p_itk__simple__Image, 0 ); -// if( !SWIG_IsOK( res ) ) -// { -// SWIG_exception_fail(SWIG_ArgError(res), "in method 'SetImageFromArray', argument needs to be of type 'sitk::Image *'"); -// } -// sitkImage = reinterpret_cast< sitk::Image * >( voidImage ); -// } -// -// try -// { -// switch( sitkImage->GetPixelIDValue() ) -// { -// case sitk::sitkUnknown: -// PyErr_SetString( PyExc_RuntimeError, "Unknown pixel type." ); -// goto fail; -// break; -// case sitk::ConditionalValue< sitk::sitkVectorUInt8 != sitk::sitkUnknown, sitk::sitkVectorUInt8, -14 >::Value: -// case sitk::ConditionalValue< sitk::sitkUInt8 != sitk::sitkUnknown, sitk::sitkUInt8, -2 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsUInt8(); -// pixelSize = sizeof( uint8_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorInt8 != sitk::sitkUnknown, sitk::sitkVectorInt8, -15 >::Value: -// case sitk::ConditionalValue< sitk::sitkInt8 != sitk::sitkUnknown, sitk::sitkInt8, -3 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsInt8(); -// pixelSize = sizeof( int8_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorUInt16 != sitk::sitkUnknown, sitk::sitkVectorUInt16, -16 >::Value: -// case sitk::ConditionalValue< sitk::sitkUInt16 != sitk::sitkUnknown, sitk::sitkUInt16, -4 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsUInt16(); -// pixelSize = sizeof( uint16_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorInt16 != sitk::sitkUnknown, sitk::sitkVectorInt16, -17 >::Value: -// case sitk::ConditionalValue< sitk::sitkInt16 != sitk::sitkUnknown, sitk::sitkInt16, -5 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsInt16(); -// pixelSize = sizeof( int16_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorUInt32 != sitk::sitkUnknown, sitk::sitkVectorUInt32, -18 >::Value: -// case sitk::ConditionalValue< sitk::sitkUInt32 != sitk::sitkUnknown, sitk::sitkUInt32, -6 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsUInt32(); -// pixelSize = sizeof( uint32_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorInt32 != sitk::sitkUnknown, sitk::sitkVectorInt32, -19 >::Value: -// case sitk::ConditionalValue< sitk::sitkInt32 != sitk::sitkUnknown, sitk::sitkInt32, -7 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsInt32(); -// pixelSize = sizeof( int32_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorUInt64 != sitk::sitkUnknown, sitk::sitkVectorUInt64, -20 >::Value: -// case sitk::ConditionalValue< sitk::sitkUInt64 != sitk::sitkUnknown, sitk::sitkUInt64, -8 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsUInt64(); -// pixelSize = sizeof( uint64_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorInt64 != sitk::sitkUnknown, sitk::sitkVectorInt64, -21 >::Value: -// case sitk::ConditionalValue< sitk::sitkInt64 != sitk::sitkUnknown, sitk::sitkInt64, -9 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsInt64(); -// pixelSize = sizeof( int64_t ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorFloat32 != sitk::sitkUnknown, sitk::sitkVectorFloat32, -22 >::Value: -// case sitk::ConditionalValue< sitk::sitkFloat32 != sitk::sitkUnknown, sitk::sitkFloat32, -10 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsFloat(); -// pixelSize = sizeof( float ); -// break; -// case sitk::ConditionalValue< sitk::sitkVectorFloat64 != sitk::sitkUnknown, sitk::sitkVectorFloat64, -23 >::Value: -// case sitk::ConditionalValue< sitk::sitkFloat64 != sitk::sitkUnknown, sitk::sitkFloat64, -11 >::Value: -// sitkBufferPtr = (void *)sitkImage->GetBufferAsDouble(); // \todo rename to Float64 for consistency -// pixelSize = sizeof( double ); -// break; -// case sitk::ConditionalValue< sitk::sitkComplexFloat32 != sitk::sitkUnknown, sitk::sitkComplexFloat32, -12 >::Value: -// case sitk::ConditionalValue< sitk::sitkComplexFloat64 != sitk::sitkUnknown, sitk::sitkComplexFloat64, -13 >::Value: -// PyErr_SetString( PyExc_RuntimeError, "Images of Complex Pixel types currently are not supported." ); -// goto fail; -// break; -// default: -// PyErr_SetString( PyExc_RuntimeError, "Unknown pixel type." ); -// goto fail; -// } -// } -// catch( const std::exception &e ) -// { -// std::string msg = "Exception thrown in SimpleITK new Image: "; -// msg += e.what(); -// PyErr_SetString( PyExc_RuntimeError, msg.c_str() ); -// goto fail; -// } -// -// -// dimension = sitkImage->GetDimension(); -// size = sitkImage->GetSize(); -// -// // if the image is a vector just treat is as another dimension -// if ( sitkImage->GetNumberOfComponentsPerPixel() > 1 ) -// { -// size.push_back( sitkImage->GetNumberOfComponentsPerPixel() ); -// } -// -// len = std::accumulate( size.begin(), size.end(), size_t(1), std::multiplies() ); -// len *= pixelSize; -// -// if ( buffer_len != len ) -// { -// PyErr_SetString( PyExc_RuntimeError, "Size mismatch of image and Buffer." ); -// goto fail; -// } -// -// memcpy( (void *)sitkBufferPtr, buffer, len ); -// -// -// PyBuffer_Release( &pyBuffer ); -// Py_RETURN_NONE; -// -//fail: -// PyBuffer_Release( &pyBuffer ); -// return NULL; -//} + +/** An internal function that performs a deep copy of the image buffer + * into a python byte array. The byte array can later be converted + * into a numpy array with the frombuffer method. + */ +static PyObject* +mitk_SetImageFromArray( PyObject *SWIGUNUSEDPARM(self), PyObject *args ) +{ + PyObject * pyImage = NULL; + + const void *buffer; + Py_ssize_t buffer_len; + Py_buffer pyBuffer; + memset(&pyBuffer, 0, sizeof(Py_buffer)); + + mitk::Image * mitkImage = NULL; + void * mitkBufferPtr = NULL; + size_t pixelSize = 1; + + unsigned int dimension = 0; + std::vector< unsigned int > size; + size_t len = 1; + + // We wish to support both the new PEP3118 buffer interface and the + // older. So we first try to parse the arguments with the new buffer + // protocol, then the old. + if (!PyArg_ParseTuple( args, "s*O", &pyBuffer, &pyImage ) ) + { + PyErr_Clear(); + +#ifdef PY_SSIZE_T_CLEAN + typedef Py_ssize_t bufSizeType; +#else + typedef int bufSizeType; +#endif + + bufSizeType _len; + // This function takes 2 arguments from python, the first is an + // python object which support the old "ReadBuffer" interface + if( !PyArg_ParseTuple( args, "s#O", &buffer, &_len, &pyImage ) ) + { + return NULL; + } + buffer_len = _len; + } + else + { + if ( PyBuffer_IsContiguous( &pyBuffer, 'C' ) != 1 ) + { + PyBuffer_Release( &pyBuffer ); + PyErr_SetString( PyExc_TypeError, "A C Contiguous buffer object is required." ); + return NULL; + } + buffer_len = pyBuffer.len; + buffer = pyBuffer.buf; + } + + /* Cast over to a sitk Image. */ + { + void * voidImage; + int res = 0; + res = SWIG_ConvertPtr( pyImage, &voidImage, SWIGTYPE_p_mitk__Image, 0 ); + if (!SWIG_IsOK(res)) + { + mitk::Image::Pointer tmpImage; + res = SWIG_ConvertPtr(pyImage, &voidImage, SWIGTYPE_p_itk__SmartPointerT_mitk__Image_t, 0); + if (!SWIG_IsOK(res)) + { + SWIG_exception_fail(SWIG_ArgError(res), "in method 'GetByteArrayFromImage', argument needs to be of type 'sitk::Image *'"); + } + tmpImage = *(reinterpret_cast(voidImage)); + voidImage = reinterpret_cast(tmpImage.GetPointer()); + } + mitkImage = reinterpret_cast< mitk::Image * >(voidImage); + } + + try + { + mitkBufferPtr = mitkImage->GetData(); + pixelSize= mitkImage->GetPixelType().GetBitsPerComponent() / 8; + } + catch( const std::exception &e ) + { + std::string msg = "Exception thrown in SimpleITK new Image: "; + msg += e.what(); + PyErr_SetString( PyExc_RuntimeError, msg.c_str() ); + goto fail; + } + + dimension = mitkImage->GetDimension(); + for (int i = 0; i < dimension; ++i) + { + size.push_back(mitkImage->GetDimension(i)); + } + + // if the image is a vector just treat is as another dimension + if (mitkImage->GetPixelType().GetNumberOfComponents() > 1) + { + size.push_back(mitkImage->GetPixelType().GetNumberOfComponents()); + } + + len = std::accumulate(size.begin(), size.end(), unsigned int(1), std::multiplies()); + len *= pixelSize; + + if ( buffer_len != len ) + { + PyErr_SetString( PyExc_RuntimeError, "Size mismatch of image and Buffer." ); + goto fail; + } + + memcpy( (void *)mitkBufferPtr, buffer, len ); + + + PyBuffer_Release( &pyBuffer ); + Py_RETURN_NONE; + +fail: + PyBuffer_Release( &pyBuffer ); + return NULL; +} #ifdef __cplusplus } // end extern "C" #endif