diff --git a/Core/Code/Algorithms/mitkImageAccessByItk.h b/Core/Code/Algorithms/mitkImageAccessByItk.h index b35452d19d..1fdf7aebd9 100644 --- a/Core/Code/Algorithms/mitkImageAccessByItk.h +++ b/Core/Code/Algorithms/mitkImageAccessByItk.h @@ -1,552 +1,620 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKIMAGEACCESSBYITK_H_HEADER_INCLUDED #define MITKIMAGEACCESSBYITK_H_HEADER_INCLUDED #include #include #include #include #include #include #include #include #include #include #include namespace mitk { /** - * \brief Exception class thrown in AccessByItk macros. + * \brief Exception class thrown in #AccessByItk macros. * - * This exception can be thrown by the invocation of the AccessByItk macros, + * This exception can be thrown by the invocation of the #AccessByItk macros, * if the MITK image is of non-expected dimension or pixel type. + * + * \ingroup Adaptor */ class AccessByItkException : public virtual std::runtime_error { public: AccessByItkException(const std::string& msg) : std::runtime_error(msg) {} ~AccessByItkException() throw() {} }; } #ifndef DOXYGEN_SKIP #define _accessByItkPixelTypeException(pixelType, pixelTypeSeq) \ { \ std::string msg("Pixel type "); \ msg.append(pixelType.GetItkTypeAsString()); \ msg.append(" is not in " MITK_PP_STRINGIZE(pixelTypeSeq)); \ throw mitk::AccessByItkException(msg); \ } #define _accessByItkDimensionException(dim, validDims) \ { \ std::stringstream msg; \ msg << "Dimension " << (dim) << " is not in " << validDims ; \ throw mitk::AccessByItkException(msg.str()); \ } #define _checkSpecificDimensionIter(r, mitkImage, dim) \ if (mitkImage->GetDimension() == dim); else #define _checkSpecificDimension(mitkImage, dimSeq) \ MITK_PP_SEQ_FOR_EACH(_checkSpecificDimensionIter, mitkImage, dimSeq) \ _accessByItkDimensionException(mitkImage->GetDimension(), MITK_PP_STRINGIZE(dimSeq)) #define _msvc_expand_bug(macro, arg) MITK_PP_EXPAND(macro arg) //-------------------------------- 0-Arg Versions -------------------------------------- #define _accessByItk(itkImageTypeFunction, pixeltype, dimension) \ if ( pixelType == typeid(pixeltype) && constImage->GetDimension() == dimension) \ { \ typedef itk::Image ImageType; \ typedef mitk::ImageToItk ImageToItkType; \ itk::SmartPointer imagetoitk = ImageToItkType::New(); \ imagetoitk->SetInput(constImage); \ imagetoitk->Update(); \ itkImageTypeFunction(imagetoitk->GetOutput()); \ } else #define _accessByItkArgs(itkImageTypeFunction, type) \ (itkImageTypeFunction, MITK_PP_TUPLE_REM(2)type) // product will be of the form (itkImageTypeFunction)(short)(2) for pixel type short and dimension 2 #ifdef _MSC_VER #define _accessByItkProductIter(r, product) \ _msvc_expand_bug(_accessByItk, _msvc_expand_bug(_accessByItkArgs, (MITK_PP_SEQ_HEAD(product), MITK_PP_SEQ_TO_TUPLE(MITK_PP_SEQ_TAIL(product))))) #else #define _accessByItkProductIter(r, product) \ MITK_PP_EXPAND(_accessByItk _accessByItkArgs(MITK_PP_SEQ_HEAD(product), MITK_PP_SEQ_TO_TUPLE(MITK_PP_SEQ_TAIL(product)))) #endif #define _accessFixedTypeByItk(itkImageTypeFunction, pixelTypeSeq, dimSeq) \ MITK_PP_SEQ_FOR_EACH_PRODUCT(_accessByItkProductIter, ((itkImageTypeFunction))(pixelTypeSeq)(dimSeq)) //-------------------------------- n-Arg Versions -------------------------------------- #define _accessByItk_n(itkImageTypeFunction, pixeltype, dimension, args) \ if ( pixelType == typeid(pixeltype) && constImage->GetDimension() == dimension) \ { \ typedef itk::Image ImageType; \ typedef mitk::ImageToItk ImageToItkType; \ itk::SmartPointer imagetoitk = ImageToItkType::New(); \ imagetoitk->SetInput(constImage); \ imagetoitk->Update(); \ itkImageTypeFunction(imagetoitk->GetOutput(), MITK_PP_TUPLE_REM(MITK_PP_SEQ_HEAD(args))MITK_PP_SEQ_TAIL(args)); \ } else #define _accessByItkArgs_n(itkImageTypeFunction, type, args) \ (itkImageTypeFunction, MITK_PP_TUPLE_REM(2) type, args) // product will be of the form ((itkImageTypeFunction)(3)(a,b,c))(short)(2) // for the variable argument list a,b,c and for pixel type short and dimension 2 #ifdef _MSC_VER #define _accessByItkProductIter_n(r, product) \ _msvc_expand_bug(_accessByItk_n, _msvc_expand_bug(_accessByItkArgs_n, (MITK_PP_SEQ_HEAD(MITK_PP_SEQ_HEAD(product)), MITK_PP_SEQ_TO_TUPLE(MITK_PP_SEQ_TAIL(product)), MITK_PP_SEQ_TAIL(MITK_PP_SEQ_HEAD(product))))) #else #define _accessByItkProductIter_n(r, product) \ MITK_PP_EXPAND(_accessByItk_n _accessByItkArgs_n(MITK_PP_SEQ_HEAD(MITK_PP_SEQ_HEAD(product)), MITK_PP_SEQ_TO_TUPLE(MITK_PP_SEQ_TAIL(product)), MITK_PP_SEQ_TAIL(MITK_PP_SEQ_HEAD(product)))) #endif #define _accessFixedTypeByItk_n(itkImageTypeFunction, pixelTypeSeq, dimSeq, va_tuple) \ MITK_PP_SEQ_FOR_EACH_PRODUCT(_accessByItkProductIter_n, (((itkImageTypeFunction)(MITK_PP_ARG_COUNT va_tuple) va_tuple))(pixelTypeSeq)(dimSeq)) #endif //DOXYGEN_SKIP /** * \brief Access a MITK image by an ITK image * * Define a templated function or method (\a itkImageTypeFunction) * within which the mitk-image (\a mitkImage) is accessed: * \code * template < typename TPixel, unsigned int VImageDimension > * void ExampleFunction( itk::Image* itkImage ); * \endcode * * The itk::Image passed to the function/method has the same * data-pointer as the mitk-image. So you have full read- and write- * access to the data vector of the mitk-image using the itk-image. * Call by: * \code * mitk::Image* inputMitkImage = ... * try * { * AccessByItk(inputMitkImage, ExampleFunction); * } * catch (const mitk::AccessByItkException& e) * { * // mitk::Image is of wrong pixel type or dimension, * // insert error handling here * } * \endcode * + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. + * * \note If your inputMitkImage is an mitk::Image::Pointer, use * inputMitkImage.GetPointer() * \note If you need to pass additional parameters to your - * access-function (\a itkImageTypeFunction), use AccessByItk_n. + * access-function (\a itkImageTypeFunction), use #AccessByItk_n. * \note If you know the dimension of your input mitk-image, * it is better to use AccessFixedDimensionByItk (less code * is generated). * \sa AccessFixedDimensionByItk * \sa AccessFixedTypeByItk * \sa AccessFixedPixelTypeByItk * \sa AccessByItk_n * * \ingroup Adaptor */ #define AccessByItk(mitkImage, itkImageTypeFunction) \ AccessFixedTypeByItk(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ) /** * \brief Access a mitk-image with known pixeltype (but unknown dimension) by an itk-image. * - * For usage, see AccessByItk. + * For usage, see #AccessByItk. * * \param pixelTypeSeq A sequence of pixel types, like (short)(char)(int) + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * If the image has a different pixel type, a mitk::AccessByItkException exception is - * thrown. If you do not know the pixel type for sure, use AccessByItk. + * thrown. If you do not know the pixel type for sure, use #AccessByItk. * * \sa AccessByItk * \sa AccessFixedDimensionByItk * \sa AccessFixedTypeByItk * \sa AccessFixedPixelTypeByItk_n * * \ingroup Adaptor */ #define AccessFixedPixelTypeByItk(mitkImage, itkImageTypeFunction, pixelTypeSeq) \ AccessFixedTypeByItk(mitkImage, itkImageTypeFunction, pixelTypeSeq, MITK_ACCESSBYITK_DIMENSIONS_SEQ) /** * \brief Access a mitk-image with an integral pixel type by an itk-image * - * See AccessByItk for details. + * See #AccessByItk for details. + * + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * \sa AccessFixedPixelTypeByItk * \sa AccessByItk * \sa AccessIntegralPixelTypeByItk_n */ #define AccessIntegralPixelTypeByItk(mitkImage, itkImageTypeFunction) \ AccessFixedTypeByItk(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ) /** * \brief Access a mitk-image with a floating point pixel type by an ITK image * - * See AccessByItk for details. + * See #AccessByItk for details. + * + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * \sa AccessFixedPixelTypeByItk * \sa AccessByItk * \sa AccessFloatingPixelTypeByItk_n */ #define AccessFloatingPixelTypeByItk(mitkImage, itkImageTypeFunction) \ AccessFixedTypeByItk(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ) /** * \brief Access a mitk-image with known dimension by an itk-image * - * For usage, see AccessByItk. + * For usage, see #AccessByItk. * * \param dimension Dimension of the mitk-image. If the image has a different dimension, * a mitk::AccessByItkException exception is thrown. + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * - * \note If you do not know the dimension for sure, use AccessByItk. + * \note If you do not know the dimension for sure, use #AccessByItk. * * \sa AccessByItk * \sa AccessFixedDimensionByItk_n * \sa AccessFixedTypeByItk * \sa AccessFixedPixelTypeByItk * * \ingroup Adaptor */ #define AccessFixedDimensionByItk(mitkImage, itkImageTypeFunction, dimension) \ AccessFixedTypeByItk(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_PIXEL_TYPES_SEQ, (dimension)) /** * \brief Access a mitk-image with known type (pixel type and dimension) by an itk-image. * * The provided mitk-image must be in the set of types created by taking the * cartesian product of the pixel type sequence and the dimension sequence. * For example, a call to * \code * AccessFixedTypeByItk(myMitkImage, MyAccessFunction, (short)(int), (2)(3)) * \endcode * asserts that the type of myMitkImage (pixeltype,dim) is in the set {(short,2),(short,3),(int,2),(int,3)}. - * For more information, see AccessByItk. + * For more information, see #AccessByItk. * * \param pixelTypeSeq A sequence of pixel types, like (short)(char)(int). * \param dimension A sequence of dimensions, like (2)(3). + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * If the image has a different dimension or pixel type, * a mitk::AccessByItkException exception is thrown. * - * \note If you do not know the dimension for sure, use AccessByItk. + * \note If you do not know the dimension for sure, use #AccessByItk. * * \sa AccessByItk * \sa AccessFixedDimensionByItk * \sa AccessFixedTypeByItk_n * \sa AccessFixedPixelTypeByItk * * \ingroup Adaptor */ #define AccessFixedTypeByItk(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq) \ { \ const mitk::PixelType& pixelType = mitkImage->GetPixelType(); \ const mitk::Image* constImage = mitkImage; \ const_cast(constImage)->Update(); \ _checkSpecificDimension(mitkImage, dimSeq); \ _accessFixedTypeByItk(itkImageTypeFunction, pixelTypeSeq, dimSeq) \ _accessByItkPixelTypeException(mitkImage->GetPixelType(), pixelTypeSeq) \ } //------------------------------ n-Arg Access Macros ----------------------------------- /** * \brief Access a MITK image by an ITK image with one or more parameters. * * Define a templated function or method (\a itkImageTypeFunction) with one ore more * additional parameters, within which the mitk-image (\a mitkImage) is accessed: * \code * template < typename TPixel, unsigned int VImageDimension > * void ExampleFunction( itk::Image* itkImage, SomeType param); * \endcode * * The itk::Image passed to the function/method has the same * data-pointer as the mitk-image. So you have full read- and write- * access to the data vector of the mitk-image using the itk-image. * Call by: * \code * SomeType param = ... * mitk::Image* inputMitkImage = ... * try * { * AccessByItk_n(inputMitkImage, ExampleFunction, (param)); * } * catch (const mitk::AccessByItkException& e) * { * // mitk::Image is of wrong pixel type or dimension, * // insert error handling here * } * \endcode * * \param va_tuple A variable length tuple containing the arguments to be passed - * to the access function, e.g. ("first", 2, THIRD) + * to the access function itkImageTypeFunction, e.g. ("first", 2, THIRD). + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * \note If your inputMitkImage is an mitk::Image::Pointer, use * inputMitkImage.GetPointer() * \note If you know the dimension of your input mitk-image, * it is better to use AccessFixedDimensionByItk_n (less code * is generated). * \sa AccessFixedDimensionByItk_n * \sa AccessFixedTypeByItk_n * \sa AccessFixedPixelTypeByItk_n * \sa AccessByItk * * \ingroup Adaptor */ #define AccessByItk_n(mitkImage, itkImageTypeFunction, va_tuple) \ AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ, va_tuple) /** * \brief Access a mitk-image with known pixeltype (but unknown dimension) by an itk-image * with one or more parameters. * - * For usage, see AccessByItk_n. + * For usage, see #AccessByItk_n. * - * \param pixelTypeSeq A sequence of pixel types, like (short)(char)(int) + * \param va_tuple A variable length tuple containing the arguments to be passed + * to the access function itkImageTypeFunction, e.g. ("first", 2, THIRD). + * \param pixelTypeSeq A sequence of pixel types, like (short)(char)(int). + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * If the image has a different pixel type, a mitk::AccessByItkException exception is - * thrown. If you do not know the pixel type for sure, use AccessByItk_n. + * thrown. If you do not know the pixel type for sure, use #AccessByItk_n. * * \sa AccessByItk_n * \sa AccessFixedDimensionByItk_n * \sa AccessFixedTypeByItk_n * \sa AccessFixedPixelTypeByItk * * \ingroup Adaptor */ #define AccessFixedPixelTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, va_tuple) \ AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, MITK_ACCESSBYITK_DIMENSIONS_SEQ, va_tuple) /** * \brief Access an mitk::Image with an integral pixel type by an ITK image with * one or more parameters. * - * See AccessByItk_n for details. + * See #AccessByItk_n for details. + * + * \param va_tuple A variable length tuple containing the arguments to be passed + * to the access function itkImageTypeFunction, e.g. ("first", 2, THIRD). + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * \sa AccessFixedPixelTypeByItk_n * \sa AccessByItk_n * \sa AccessIntegralPixelTypeByItk */ #define AccessIntegralPixelTypeByItk_n(mitkImage, itkImageTypeFunction, va_tuple) \ AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ, va_tuple) /** * \brief Access an mitk::Image with a floating point pixel type by an ITK image * with one or more parameters. * - * See AccessByItk_n for details. + * See #AccessByItk_n for details. + * + * \param va_tuple A variable length tuple containing the arguments to be passed + * to the access function itkImageTypeFunction, e.g. ("first", 2, THIRD). + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * \sa AccessFixedPixelTypeByItk_n * \sa AccessByItk_n * \sa AccessFloatingPixelTypeByItk */ #define AccessFloatingPixelTypeByItk_n(mitkImage, itkImageTypeFunction, va_tuple) \ AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ, va_tuple) /** * \brief Access a mitk-image with known dimension by an itk-image with * one or more parameters. * - * For usage, see AccessByItk_n. + * For usage, see #AccessByItk_n. * * \param dimension Dimension of the mitk-image. If the image has a different dimension, * a mitk::AccessByItkException exception is thrown. + * \param va_tuple A variable length tuple containing the arguments to be passed + * to the access function itkImageTypeFunction, e.g. ("first", 2, THIRD). + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * - * \note If you do not know the dimension for sure, use AccessByItk_n. + * \note If you do not know the dimension for sure, use #AccessByItk_n. * * \sa AccessByItk_n * \sa AccessFixedDimensionByItk * \sa AccessFixedTypeByItk_n * \sa AccessFixedPixelTypeByItk_n * * \ingroup Adaptor */ #define AccessFixedDimensionByItk_n(mitkImage, itkImageTypeFunction, dimension, va_tuple) \ AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, MITK_ACCESSBYITK_PIXEL_TYPES_SEQ, (dimension), va_tuple) /** * \brief Access a mitk-image with known type (pixel type and dimension) by an itk-image * with one or more parameters. * * For usage, see AccessFixedTypeByItk. * * \param pixelTypeSeq A sequence of pixel types, like (short)(char)(int). * \param dimension A sequence of dimensions, like (2)(3). + * \param va_tuple A variable length tuple containing the arguments to be passed + * to the access function itkImageTypeFunction, e.g. ("first", 2, THIRD). + * \param mitkImage The MITK input image. + * \param itkImageTypeFunction The templated access-function to be called. + * + * \throws mitk::AccessByItkException If mitkImage is of unsupported pixel type or dimension. * * If the image has a different dimension or pixel type, * a mitk::AccessByItkException exception is thrown. * - * \note If you do not know the dimension for sure, use AccessByItk_n. + * \note If you do not know the dimension for sure, use #AccessByItk_n. * * \sa AccessByItk_n * \sa AccessFixedDimensionByItk_n * \sa AccessFixedTypeByItk * \sa AccessFixedPixelTypeByItk_n * * \ingroup Adaptor */ #define AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq, va_tuple) \ { \ const mitk::PixelType& pixelType = mitkImage->GetPixelType(); \ const mitk::Image* constImage = mitkImage; \ const_cast(constImage)->Update(); \ _checkSpecificDimension(mitkImage, dimSeq); \ _accessFixedTypeByItk_n(itkImageTypeFunction, pixelTypeSeq, dimSeq, va_tuple) \ _accessByItkPixelTypeException(mitkImage->GetPixelType(), pixelTypeSeq) \ } //------------------------- For back-wards compatibility ------------------------------- #define AccessByItk_1(mitkImage, itkImageTypeFunction, arg1) AccessByItk_n(mitkImage, itkImageTypeFunction, (arg1)) #define AccessFixedPixelTypeByItk_1(mitkImage, itkImageTypeFunction, pixelTypeSeq, arg1) AccessFixedPixelTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, (arg1)) #define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1) AccessFixedDimensionByItk_n(mitkImage, itkImageTypeFunction, dimension, (arg1)) #define AccessFixedTypeByItk_1(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq, arg1) AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq, (arg1)) #define AccessByItk_2(mitkImage, itkImageTypeFunction, arg1, arg2) AccessByItk_n(mitkImage, itkImageTypeFunction, (arg1,arg2)) #define AccessFixedPixelTypeByItk_2(mitkImage, itkImageTypeFunction, pixelTypeSeq, arg1, arg2) AccessFixedPixelTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, (arg1,arg2)) #define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2) AccessFixedDimensionByItk_n(mitkImage, itkImageTypeFunction, dimension, (arg1,arg2)) #define AccessFixedTypeByItk_2(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq, arg1, arg2) AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq, (arg1,arg2)) #define AccessByItk_3(mitkImage, itkImageTypeFunction, arg1, arg2, arg3) AccessByItk_n(mitkImage, itkImageTypeFunction, (arg1,arg2,arg3)) #define AccessFixedPixelTypeByItk_3(mitkImage, itkImageTypeFunction, pixelTypeSeq, arg1, arg2, arg3) AccessFixedPixelTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, (arg1,arg2,arg3)) #define AccessFixedDimensionByItk_3(mitkImage, itkImageTypeFunction, dimension, arg1, arg2, arg3) AccessFixedDimensionByItk_n(mitkImage, itkImageTypeFunction, dimension, (arg1,arg2,arg3)) #define AccessFixedTypeByItk_3(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq, arg1, arg2, arg3) AccessFixedTypeByItk_n(mitkImage, itkImageTypeFunction, pixelTypeSeq, dimSeq, (arg1,arg2,arg3)) //----------------------------- Access two MITK Images --------------------------------- #ifndef DOXYGEN_SKIP #define _accessTwoImagesByItk(itkImageTypeFunction, pixeltype1, dim1, pixeltype2, dim2) \ if (pixelType1 == typeid(pixeltype1) && pixelType2 == typeid(pixeltype2) && \ constImage1->GetDimension() == dim1 && constImage2->GetDimension() == dim2) \ { \ typedef itk::Image ImageType1; \ typedef itk::Image ImageType2; \ typedef mitk::ImageToItk ImageToItkType1; \ typedef mitk::ImageToItk ImageToItkType2; \ itk::SmartPointer imagetoitk1 = ImageToItkType1::New(); \ imagetoitk1->SetInput(constImage1); \ imagetoitk1->Update(); \ itk::SmartPointer imagetoitk2 = ImageToItkType2::New(); \ imagetoitk2->SetInput(constImage2); \ imagetoitk2->Update(); \ itkImageTypeFunction(imagetoitk1->GetOutput(), imagetoitk2->GetOutput()); \ } else #define _accessTwoImagesByItkArgs2(itkImageTypeFunction, type1, type2) \ (itkImageTypeFunction, MITK_PP_TUPLE_REM(2) type1, MITK_PP_TUPLE_REM(2) type2) #define _accessTwoImagesByItkArgs(product) \ MITK_PP_EXPAND(_accessTwoImagesByItkArgs2 MITK_PP_EXPAND((MITK_PP_SEQ_HEAD(product), MITK_PP_TUPLE_REM(2) MITK_PP_SEQ_TO_TUPLE(MITK_PP_SEQ_TAIL(product))))) // product is of the form (itkImageTypeFunction)((short,2))((char,2)) #ifdef _MSC_VER #define _accessTwoImagesByItkIter(r, product) \ MITK_PP_EXPAND(_accessTwoImagesByItk _msvc_expand_bug(_accessTwoImagesByItkArgs2, (MITK_PP_SEQ_HEAD(product), _msvc_expand_bug(MITK_PP_TUPLE_REM(2), MITK_PP_EXPAND(MITK_PP_SEQ_TO_TUPLE (MITK_PP_SEQ_TAIL(product))))))) #else #define _accessTwoImagesByItkIter(r, product) \ MITK_PP_EXPAND(_accessTwoImagesByItk _accessTwoImagesByItkArgs(product)) #endif #define _accessTwoImagesByItkForEach(itkImageTypeFunction, tseq1, tseq2) \ MITK_PP_SEQ_FOR_EACH_PRODUCT(_accessTwoImagesByItkIter, ((itkImageTypeFunction))(tseq1)(tseq2)) #endif // DOXYGEN_SKIP /** * \brief Access two mitk-images with known dimension by itk-images * * Define a templated function or method (\a itkImageTypeFunction) * within which the mitk-images (\a mitkImage1 and \a mitkImage2) are accessed: * \code * template * void ExampleFunctionTwoImages(itk::Image* itkImage1, itk::Image* itkImage2); * \endcode * * The itk::Image passed to the function/method has the same * data-pointer as the mitk-image. So you have full read- and write- * access to the data vector of the mitk-image using the itk-image. * Call by: * \code * mitk::Image* inputMitkImage1 = ... * mitk::Image* inputMitkImage2 = ... * try * { * AccessTwoImagesFixedDimensionByItk(inputMitkImage1, inputMitkImage2, ExampleFunctionTwoImages, 3); * } * catch (const mitk::AccessByItkException& e) * { * // mitk::Image arguments are of wrong pixel type or dimension, * // insert error handling here * } * \endcode * - * If one of the images has a different dimension, a mitk::AccessByItkException exception is thrown. - * * \note If your inputMitkImage1 or inputMitkImage2 is a mitk::Image::Pointer, use * inputMitkImage1.GetPointer(). * - * \param itkImageTypeFunction The name of the template function to be called. + * \param mitkImage1 The first MITK input image. + * \param mitkImage1 The second MITK input image. + * \param itkImageTypeFunction The name of the template access-function to be called. * \param dimension Dimension of the two mitk-images. * - * \sa AccessByItk + * \throws mitk::AccessByItkException If mitkImage1 and mitkImage2 have different dimensions or + * one of the images is of unsupported pixel type or dimension. + * + * \sa #AccessByItk * * \ingroup Adaptor */ #define AccessTwoImagesFixedDimensionByItk(mitkImage1, mitkImage2, itkImageTypeFunction, dimension) \ { \ const mitk::PixelType& pixelType1 = mitkImage1->GetPixelType(); \ const mitk::PixelType& pixelType2 = mitkImage2->GetPixelType(); \ const mitk::Image* constImage1 = mitkImage1; \ const mitk::Image* constImage2 = mitkImage2; \ const_cast(constImage1)->Update(); \ const_cast(constImage2)->Update(); \ _checkSpecificDimension(mitkImage1, (dimension)); \ _checkSpecificDimension(mitkImage2, (dimension)); \ _accessTwoImagesByItkForEach(itkImageTypeFunction, MITK_ACCESSBYITK_TYPES_DIMN_SEQ(dimension), MITK_ACCESSBYITK_TYPES_DIMN_SEQ(dimension)) \ { \ std::string msg("Pixel type "); \ msg.append(pixelType1.GetItkTypeAsString()); \ msg.append(" or pixel type "); \ msg.append(pixelType2.GetItkTypeAsString()); \ msg.append(" is not in " MITK_PP_STRINGIZE(MITK_ACCESSBYITK_TYPES_DIMN_SEQ(dimension))); \ throw mitk::AccessByItkException(msg); \ } \ } #endif // of MITKIMAGEACCESSBYITK_H_HEADER_INCLUDED diff --git a/Core/Code/Algorithms/mitkInstantiateAccessFunctions.h b/Core/Code/Algorithms/mitkInstantiateAccessFunctions.h index 252f22cd6c..76e3efa355 100644 --- a/Core/Code/Algorithms/mitkInstantiateAccessFunctions.h +++ b/Core/Code/Algorithms/mitkInstantiateAccessFunctions.h @@ -1,148 +1,159 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKINSTANTIATEACCESSFUNCTIONS_H_HEADER_INCLUDED #define MITKINSTANTIATEACCESSFUNCTIONS_H_HEADER_INCLUDED #include #include #include #include #include #include #include #include #include #ifndef DOXYGEN_SKIP #define InstantiateAccessFunctionImpl(r, itkImgFunc, type) \ MITK_PP_CAT(InstantiateAccessFunction_, itkImgFunc) type // product is of the form (itkImgFunc)(short)(2) #ifdef _MSC_VER #define InstantiateAccessFunctionProductImpl(r, product) \ MITK_PP_CAT(InstantiateAccessFunction_, MITK_PP_SEQ_HEAD(product)) \ MITK_PP_EXPAND(MITK_PP_SEQ_TO_TUPLE(MITK_PP_SEQ_TAIL(product))) #else #define InstantiateAccessFunctionProductImpl(r, product) \ MITK_PP_EXPAND(MITK_PP_CAT(InstantiateAccessFunction_, MITK_PP_SEQ_HEAD(product)) \ MITK_PP_SEQ_TO_TUPLE(MITK_PP_SEQ_TAIL(product))) #endif #endif // DOXYGEN_SKIP //--------------------------------- instantiation functions ------------------------------ /** * \brief Instantiate access function for the given pixel types and dimensions. * * Iteratively calls a macro named InstantiateAccessFunction_itkImgFunc * which you must define and which usually explicitly instantiates your access function. * * A call to InstantiateAccessFunctionForFixedPixelType(T, (a)(b), (d)(e)) results in calls * - * InstantiateAccessFunction_T(a, d) - * InstantiateAccessFunction_T(a, e) - * InstantiateAccessFunction_T(b, d) + * InstantiateAccessFunction_T(a, d)
+ * InstantiateAccessFunction_T(a, e)
+ * InstantiateAccessFunction_T(b, d)
* InstantiateAccessFunction_T(b, e) * * That is, InstantiateAccessFunction_T is called for the cartesian product of the sequences pixelTypeSeq * and dimSeq. * * Example: * \code * template * void MyImageAccessFunction(itk::Image* itkImage) * { ... } * - * #define InstantiateAccessFunction_MyImageAccessFunction(pixelType, dim) \\ + * #define InstantiateAccessFunction_MyImageAccessFunction(pixelType, dim) \ * template void MyImageAccessFunction(itk::Image*); * * InstantiateAccessFunctionForFixedPixelType(MyImageAccessFunction, (int), (3)) * \endcode * * Use this macro once after the definition of your access function. * Some compilers have memory problems without the explicit instantiation. * You may need to move the access function to a separate file. The CMake macro * MITK_MULTIPLEX_PICTYPE can help you with that. See \c mitk/CMake/mitkMacroMultiplexPicType.cmake * for documentation. * + * \param itkImgFunc The custom part of the name of the macro to be called. * \param pixelTypeSeq a sequence of types, like (int)(short)(char). * \param dimSeq a sequence of dimensions, like (2)(3). * * \ingroup Adaptor */ #define InstantiateAccessFunctionForFixedType(itkImgFunc, pixelTypeSeq, dimSeq) \ MITK_PP_SEQ_FOR_EACH_PRODUCT(InstantiateAccessFunctionProductImpl, ((itkImgFunc))(pixelTypeSeq)(dimSeq)) /** * \brief Instantiate access function for all datatypes and dimensions. * * \sa InstantiateAccessFunctionForFixedType * * \ingroup Adaptor */ #define InstantiateAccessFunction(itkImgFunc) \ InstantiateAccessFunctionForFixedDimension(itkImgFunc, 2) \ InstantiateAccessFunctionForFixedDimension(itkImgFunc, 3) /** * \brief Instantiate access function for all datatypes and a specific dimension. * * \sa InstantiateAccessFunctionForFixedType * + * \param itkImgFunc The custom part of the name of the macro to be called. + * \param dimSeq a sequence of dimensions, like (2)(3). + * * \ingroup Adaptor */ #define InstantiateAccessFunctionForFixedDimension(itkImgFunc, dim) \ InstantiateAccessFunctionForFixedType(itkImgFunc, MITK_ACCESSBYITK_TYPES_SEQ, (dim)) /** * \brief Instantiate access function for all given pixel types and all dimensions. * * \sa InstantiateAccessFunctionForFixedType * + * \param itkImgFunc The custom part of the name of the macro to be called. + * \param pixelTypeSeq a sequence of types, like (int)(short)(char). + * * \ingroup Adaptor */ #define InstantiateAccessFunctionForFixedPixelType(itkImgFunc, pixelTypeSeq) \ InstantiateAccessFunctionForFixedType(itkImgFunc, pixelTypeSeq, MITK_ACCESSBYITK_DIMENSIONS_SEQ) /** * \brief Instantiate access function for integral datatypes and all dimensions. * * \sa InstantiateAccessFunctionForFixedType * + * \param itkImgFunc The custom part of the name of the macro to be called. + * * \ingroup Adaptor */ #define InstantiateAccessFunctionForIntegralPixelTypes(itkImgFunc) \ InstantiateAccessFunctionForFixedType(itkImgFunc, MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ) /** * \brief Instantiate access function for floating point datatypes and all dimensions. * * \sa InstantiateAccessFunctionForFixedType * + * \param itkImgFunc The custom part of the name of the macro to be called. + * * \ingroup Adaptor */ #define InstantiateAccessFunctionForFloatingPixelTypes(itkImgFunc) \ InstantiateAccessFunctionForFixedType(itkImgFunc, MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES_SEQ, MITK_ACCESSBYITK_DIMENSIONS_SEQ) #endif // of MITKINSTANTIATEACCESSFUNCTIONS_H_HEADER_INCLUDED diff --git a/Documentation/Doxygen/Modules/ModuleAdaptors.dox b/Documentation/Doxygen/Modules/ModuleAdaptors.dox index d974d0508a..b720121389 100644 --- a/Documentation/Doxygen/Modules/ModuleAdaptors.dox +++ b/Documentation/Doxygen/Modules/ModuleAdaptors.dox @@ -1,102 +1,142 @@ namespace mitk { /** \defgroup Adaptor Adaptor Classes \ingroup ProcessAdaptor \brief This subcategory includes adaptor classes for the integration of algorithms from other toolkits, especially ITK. -The task of most of the classes in this category is to deal with the conversion between the (templated) itk::Image and the (not-templated) mitk::Image. +The task of most of the classes in this category is to deal with the conversion between +the (templated) itk::Image and the (not-templated) mitk::Image. Methods for conversion are provided for both directions: \li \ref MitkToItk \li \ref ItkToMitk Care has to be taken regarding the involved coordinate systems, see \ref ItkToMitkCoordinateSystems. For limitations on ITK-type conversion see the section \ref Limitations. -VTK-based access to MITK images is straightforward: simply ask your mitk::Image for a \a vtkImageData by calling Image:GetVtkImageData. -Similarily, to get a \a vtkPolyData from the MITK class for storing surfaces, mitk::Surface, call Surface::GetVtkPolyData. +VTK-based access to MITK images is straightforward: simply ask your mitk::Image for a +\a vtkImageData by calling Image:GetVtkImageData. Similarily, to get a \a vtkPolyData +from the MITK class for storing surfaces, mitk::Surface, call Surface::GetVtkPolyData. \section MitkToItk MITK to ITK adaptors -Pixel type and dimension of MITK images can be specified at run time whereas ITK images are templated over the pixel type and the dimension, thus in ITK both need to be specified at compile time. +Pixel type and dimension of MITK images can be specified at run time whereas ITK images +are templated over the pixel type and the dimension, thus in ITK both need to be specified +at compile time. There two different situations, which are covered in the following sub-sections: -\li Either you know the pixel type/dimension the ITK image should have at compile time for some reason (e.g., you always create MITK images of a specific pixel type/dimension) -\li or the pixel type/dimension of an MITK image is really unkown and the ITK image should have the same (unkown) type. +\li Either you know the pixel type/dimension the ITK image should have at compile time for + some reason (e.g., you always create MITK images of a specific pixel type/dimension) +\li or the pixel type/dimension of an MITK image is really unkown and the ITK image should + have the same (unkown) type. \subsection MitkToFixedItk Converting MITK images to ITK images with known type If you know the type (pixel type and dimension) of the MITK image you have two options: -\li mitk::ImageToItk: is a process class that takes an mitk::Image as input and produces an itk::Image of the given type \a TOutputImage as output (to be access using \a GetOutput()). In case the MITK image does not have the same type as \a TOutputImage an exception will be thrown. -\li mitk::CastToItkImage: this function has two parameters, the mitk::Image (input) and a smartpointer to an itk::Image (output, does not need to be initialized). In case the MITK image does not have the same type as the ITK image it will be casted (if possible; done via itk::CastImageFilter). - -Thus, mitk::CastToItkImage is the more powerful variant: here it is sufficient that you know what you want to have (the ITK data type), to which the MITK image will be casted, if needed. +\li mitk::ImageToItk: is a process class that takes an mitk::Image as input + and produces an itk::Image of the given type \a TOutputImage as output (to be accessed + using \a GetOutput()). In case the MITK image does not have the same type as + \a TOutputImage an exception will be thrown. +\li mitk::CastToItkImage: this function has two parameters, the mitk::Image (input) and a + smartpointer to an itk::Image (output, does not need to be initialized). In case the + MITK image does not have the same type as the ITK image it will be casted + (if possible; done via itk::CastImageFilter). + +Thus, mitk::CastToItkImage is the more powerful variant: here it is sufficient that you know +what you want to have (the ITK data type), to which the MITK image will be casted, if needed. \subsection MitkToUnkownItk Accessing an MITK image as an ITK image (type unkown) -If you do not know the pixel type/dimension of an MITK image in advance and the ITK image should have the same (unkown) type, e.g., to run a filter on the MITK image data, we cannot really convert to one ITK image. This is simply, because we cannot instantiate an itk::Image object with unkown pixel type/dimension. +If you do not know the pixel type/dimension of an MITK image in advance and the ITK image should +have the same (unkown) type, e.g., to run a filter on the MITK image data, we cannot really convert +to one ITK image. This is simply, because we cannot instantiate an itk::Image object with unkown +pixel type/dimension. Nevertheless, MITK provides a way to access an MITK image as if it was an ITK image of unkown type. To do so, first define an access method, which is templated as an ITK image is: \code template MyAccessMethod(itk::Image* itkImage) { ... } \endcode -If you don't understand this template syntax, we need to refer you to an C++ text book. Understanding template syntax is crucial to successfully using ITK. +If you don't understand this template syntax, we need to refer you to an C++ text book. Understanding +template syntax is crucial to successfully using ITK. -To call this templated method with an (untemplated) mitk::Image, you can use the AccessByItk macro (or one of its variants) from mitkImageAccessByItk.h. This macro checks for -the actual image type of the mitk::Image and does any neccessary conversions. This works for all typical pixel types and for dimension 2 and 3. +To call this templated method with an (untemplated) mitk::Image, you can use the #AccessByItk macro +(or one of its variants) from mitkImageAccessByItk.h. This macro checks for the actual image type of +the mitk::Image and does any neccessary conversions. This works for all configured pixel types (default +is char, unsigned char, short, unsigned short, int, unsigned int, float, and double) and dimensions +(default is 2 and 3). You can change the considered default pixel types and dimensions by modifying +the CMake variables MITK_ACCESSBYITK_*. \code AccessByItk(mitkImage, MyAccessMethod) \endcode An example is given in \ref Step6Page. -The AccessBy... macros create quite a lot of code: the user defined access method has to be compiled for all typical pixel types \em times the two supported dimensions (2 and 3). Therefore, depending on the complexity of the access method, some compilers may run into problems with memory. -One workaround is to use explicit instantiation and distribute it on multiple files. The macros InstantiateAccessFunction... are for this purpose. -An example is again given in \ref Step6Page. -Another workaround is to reduce the created code by fixing either the type (AccessFixedTypeByItk) or dimension (AccessFixedDimensionByItk). +The AccessBy... macros create quite a lot of code: the user defined access method has to be compiled for +all considered pixel types \em times the supported dimensions (default is 2 and 3). Therefore, depending +on the complexity of the access method, some compilers may run into problems with memory. +One workaround is to use explicit instantiation and distribute it on multiple files. The macro +#InstantiateAccessFunction and its variants are for this purpose. An example is again given in \ref Step6Page. +Another workaround is to reduce the created code by fixing either the type (#AccessFixedTypeByItk) or +dimension (#AccessFixedDimensionByItk). -There are variants for additional parameters for AccessByItk... and InstantiateAccessFunction..., e.g., AccessFixedTypeByItk_2 allows to pass two additional parameters to the access-function. +There is one variant of AccessByItk... for passing additional parameters +to the access-function, called #AccessFixedTypeByItk_n. \link mitkImage.h \endlink \link mitkImageCast.h \endlink \link mitkImageToItk.h \endlink \link mitkITKImageImport.h \endlink \section ItkToMitk ITK to MITK adaptors Converting ITK images to MITK is easier than the other way round. Basically, you have three options: -\li mitk::ITKImageImport: is a process class that takes an itk::Image of the given type \a TOutputImage as input and produces an mitk::Image as output (to be access using \a GetOutput()). The image data contained in the itk::Image is referenced, not copied. -\li mitk::ImportItkImage: this function takes the itk::Image as input and returns an mitk::Image. Internally, it uses the class just described. So again, the image data contained in the itk::Image is referenced, not copied. -\li mitk::CastToMitkImage: this function has two parameters, the itk::Image (input) and a smartpointer to an mitk::Image (output, does not need to be initialized). In contrast to the other described methods, this functions copies the image data! +\li mitk::ITKImageImport: is a process class that takes an itk::Image of the given type + \a TOutputImage as input and produces an mitk::Image as output (to be accessed using \a GetOutput()). + The image data contained in the itk::Image is referenced, not copied. +\li mitk::ImportItkImage: this function takes the itk::Image as input and returns an mitk::Image. Internally, + it uses the class just described. So again, the image data contained in the itk::Image is referenced, not + copied. +\li mitk::CastToMitkImage: this function has two parameters, the itk::Image (input) and a smartpointer to an + mitk::Image (output, does not need to be initialized). In contrast to the other described methods, + this function copies the image data! \section ItkToMitkCoordinateSystems ITK image vs MITK coordinate systems -Converting coordinates from the ITK physical coordinate system (which does not support rotated images) to the MITK world coordinate system should be performed via the Geometry3D of the Image, see mitk::Geometry3D::WorldToItkPhysicalPoint. +Converting coordinates from the ITK physical coordinate system (which does not support rotated images) to the +MITK world coordinate system should be performed via the Geometry3D of the Image, +see mitk::Geometry3D::WorldToItkPhysicalPoint. \section Limitations Limitations -The \ref MitkToItk for unspecified types have to do type multiplexing at compile time. This is done for a limited number of pixel types (\a char, \a short, \a int, \a long, \a double, \a float, and the \a unsigned variants of the integer data types) and for dimensions 2 and 3. +The \ref MitkToItk for unspecified types have to do type multiplexing at compile time. This is done for a +limited number of pixel types and dimensions, defined during the CMake configuration process. -Especially, color image types are not multiplexed. This is because many algorithms do not support color images (e.g. with data type itk::RGBPixel) because they do not have a scalar data type. If your algorithm do support color and you want to multiplex over all scalar as well as the color data type, try the following: +Especially, color image types are not multiplexed. This is because many algorithms do not support color images +(e.g. with data type itk::RGBPixel) because they do not have a scalar data type. If your algorithm do support +color and you want to multiplex over all scalar as well as the color data type, try the following: \code - if (myMitkImageThatMaybeColor->GetPixelType()==typeid(itk::RGBPixel)) - { - AccessFixedPixelTypeByItk(myMitkImageThatMaybeColor, myAlgorithmFunction, itk::RGBPixel); - } - else - { - AccessByItk(myMitkImageThatMaybeColor, myAlgorithmFunction); - } +try +{ + AccessFixedPixelTypeByItk(myMitkImageThatMaybeColor, // The MITK image which may be a color image + myAlgorithmFunction, // The template method being able to handle color + MITK_ACCESSBYITK_PIXEL_TYPES_SEQ // The default pixel type sequence + (itk::RGBPixel) // The additional type sequence + ) +} +catch(const mitk::AccessByItkException& e) +{ + // add error handling here +} \endcode */ }