MeVisLabToolboxReference
FMEwork/ITK/Sources/ITK/MLITK/ITKSupport/mlITKSupportToolFunctions.h
Go to the documentation of this file.
00001 // **InsertLicense** code
00002 //----------------------------------------------------------------------------------
00005 
00010 //----------------------------------------------------------------------------------
00011 #ifndef __mlITKSupportToolFunctions_H
00012 #define __mlITKSupportToolFunctions_H
00013 
00015 // Include dll-specific settings.
00016 #include "mlInitSystemITKSupport.h"
00017 
00019 #ifndef __mlModuleIncludes_H
00020 #include "mlModuleIncludes.h"
00021 #endif
00022 
00024 #ifndef __mlPointList_H
00025 #include "mlPointList.h"
00026 #endif
00027 #ifndef __mlVectorList_H
00028 #include "mlVectorList.h"
00029 #endif
00030 #ifndef __mlXMarkerList_H
00031 #include "mlXMarkerList.h"
00032 #endif
00033 
00034 
00036 #include <itkImage.h>
00037 #include <itkImportImageFilter.h>
00038 #include <itkMatrix.h>
00039 #include <itkPointSet.h>
00040 
00041 ML_START_NAMESPACE
00042 
00043 //---------------------------------------------------------------------------
00053 //---------------------------------------------------------------------------
00054 extern MLITK_SUPPORT_EXPORT void postITKException(const itk::ExceptionObject &e,
00055                                                   const Module               *module,
00056                                                   MLMessageType              messageType,
00057                                                   const std::string          &handling="");
00058 
00059 
00060 
00061 //---------------------------------------------------------------------------
00067 //------------------------------------------------------------------------------------
00068 extern MLITK_SUPPORT_EXPORT void copyITKDataBufferToMLSubImg(void              *itkData,
00069                                                              size_t            itkDataTypeSize,
00070                                                              const SubImageBox &itkBox,
00071                                                              SubImage          &outSubImg);
00072 
00073 
00074 //---------------------------------------------------------------------------
00084 //---------------------------------------------------------------------------
00085 template<typename SIZE_TYPE>
00086 SIZE_TYPE ITKSizeFromMLVector(const ImageVector &vec)
00087 {
00088   ML_TRACE_IN("template ITKSizeFromMLVector()");
00089 
00090   SIZE_TYPE sizeObj;
00091   if (sizeObj.GetSizeDimension() > static_cast<unsigned int>(vec.dim())){
00092     ML_PRINT_FATAL_ERROR("ITKSizeFromMLVector", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions.");
00093   }
00094   else{
00095     for (unsigned int i=0; i<sizeObj.GetSizeDimension(); i++){ sizeObj[i] = vec[i]; }
00096   }
00097   return sizeObj;
00098 }
00099 
00100 //---------------------------------------------------------------------------
00110 //---------------------------------------------------------------------------
00111 template<typename INDEX_TYPE>
00112 INDEX_TYPE ITKIndexFromMLVector(const ImageVector &vec)
00113 {
00114   ML_TRACE_IN("template ITKIndexFromMLVector()");
00115 
00116   INDEX_TYPE sizeObj;
00117   if (sizeObj.GetIndexDimension() > static_cast<unsigned int>(vec.dim())){
00118     ML_PRINT_FATAL_ERROR("ITKIndexFromMLVector", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions.");
00119   }
00120   else{
00121     for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){ sizeObj[i] = vec[i]; }
00122   }
00123   return sizeObj;
00124 }
00125 
00126 //---------------------------------------------------------------------------
00135 //---------------------------------------------------------------------------
00136 template<typename INDEX_TYPE>
00137 ImageVector MLVectorFromITKSize(const INDEX_TYPE &sizeObj, MLint defaultVal)
00138 {
00139   ML_TRACE_IN("template MLVectorFromITKSize()");
00140 
00141   ImageVector vec(0);
00142   unsigned int sizeDim = sizeObj.GetSizeDimension();
00143   unsigned int vecDim  = static_cast<unsigned int>(vec.dim());
00144   if (sizeDim > vecDim){
00145     sizeDim = vecDim;
00146     ML_PRINT_WARNING("MLVectorFromITKSize", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored.");
00147   }
00148 
00149   for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < sizeDim) ? sizeObj[i] : defaultVal; }
00150   return vec;
00151 }
00152 
00153 //---------------------------------------------------------------------------
00164 //---------------------------------------------------------------------------
00165 template<typename INDEX_TYPE>
00166 ImageVector MLVectorFromITKIndex(const INDEX_TYPE &indexObj, MLint defaultVal)
00167 {
00168   ML_TRACE_IN("template MLVectorFromITKIndex()");
00169 
00170   ImageVector vec(0);
00171   unsigned int idxDim = indexObj.GetIndexDimension();
00172   unsigned int vecDim = static_cast<unsigned int>(vec.dim());
00173   if (idxDim > vecDim){
00174     idxDim = vecDim;
00175     ML_PRINT_WARNING("MLVectorFromITKIndex", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored.");
00176   }
00177 
00178   for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < idxDim) ? indexObj[i] : defaultVal; }
00179   return vec;
00180 }
00181 
00182 //---------------------------------------------------------------------------
00194 //---------------------------------------------------------------------------
00195 template<typename VECTOR_TYPE>
00196 VECTOR_TYPE ITKVectorFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
00197 {
00198   ML_TRACE_IN("template ITKVectorFromMLVec3()");
00199 
00200   VECTOR_TYPE sizeObj;
00201   for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){
00202     sizeObj[i] = i < 3 ? vec[i] : defaultComp;
00203   }
00204   return sizeObj;
00205 }
00206 
00207 //---------------------------------------------------------------------------
00219 //---------------------------------------------------------------------------
00220 template<typename VECTOR_TYPE>
00221 VECTOR_TYPE ITKVectorFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
00222 {
00223   ML_TRACE_IN("template ITKVectorFromMLVec4()");
00224 
00225   VECTOR_TYPE sizeObj;
00226   for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){
00227     sizeObj[i] = i < 4 ? vec[i] : defaultComp;
00228   }
00229   return sizeObj;
00230 }
00231 
00232 //---------------------------------------------------------------------------
00244 //---------------------------------------------------------------------------
00245 template<typename POINT_TYPE>
00246 POINT_TYPE ITKPointFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
00247 {
00248   ML_TRACE_IN("template ITKPointFromMLVec3()");
00249 
00250   POINT_TYPE sizeObj;
00251   for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){
00252     sizeObj[i] = i < 3 ? vec[i] : defaultComp;
00253   }
00254   return sizeObj;
00255 }
00256 
00257 //---------------------------------------------------------------------------
00269 //---------------------------------------------------------------------------
00270 template<typename POINT_TYPE>
00271 POINT_TYPE ITKPointFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
00272 {
00273   ML_TRACE_IN("template ITKPointFromMLVec4()");
00274 
00275   POINT_TYPE sizeObj;
00276   for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){
00277     sizeObj[i] = i < 4 ? vec[i] : defaultComp;
00278   }
00279   return sizeObj;
00280 }
00281 
00282 
00283 //---------------------------------------------------------------------------
00293 //---------------------------------------------------------------------------
00294 template<typename REGION_PARENT_TYPE>
00295 typename REGION_PARENT_TYPE::RegionType ITKRegionFromMLSubImgBox(const SubImageBox &subImgBox)
00296 {
00297   ML_TRACE_IN("template ITKRegionFromMLSubImgBox()");
00298 
00299   typename REGION_PARENT_TYPE::RegionType region;
00300 
00301   // Set ITK region origin to the ML SubImageBox origin.
00302   region.SetIndex(ITKIndexFromMLVector<ITKML_TYPENAME REGION_PARENT_TYPE::IndexType>(subImgBox.v1));
00303 
00304   // Set ITK region extent to the ML SubImageBox extent.
00305   region.SetSize(ITKSizeFromMLVector<ITKML_TYPENAME REGION_PARENT_TYPE::SizeType>(subImgBox.getExtent()));
00306   return region;
00307 }
00308 
00309 //---------------------------------------------------------------------------
00317 //---------------------------------------------------------------------------
00318 template<typename REGION_PARENT_TYPE>
00319 SubImageBox MLSubImgBoxFromITKRegion(const typename REGION_PARENT_TYPE::RegionType &region)
00320 {
00321   ML_TRACE_IN("template MLSubImgBoxFromITKRegion()");
00322 
00323   // Get ITK region origin into the ML SubImageBox origin.
00324   // For dimensions not specified by ITK use coordinate 0.
00325   SubImageBox box;
00326   box.v1 = MLVectorFromITKIndex(region.GetIndex(), 0);
00327 
00328   // Get ITK region extent into the ML SubImageBox extent.
00329   // For dimensions not specified by ITK use extent 1.
00330   ImageVector ext = MLVectorFromITKSize(region.GetSize(), 1);
00331 
00332   // Return the constructed SubImageBox.
00333   box.v2 = box.v1 + (ext - ImageVector(1));
00334   return box;
00335 }
00336 
00337 //---------------------------------------------------------------------------
00340 //---------------------------------------------------------------------------
00341 template<typename ARRAY_TYPE, typename STL_VECTOR>
00342 ARRAY_TYPE ITKArrayFromSTLVector(const STL_VECTOR &stlVec)
00343 {
00344   ML_TRACE_IN("template ITKArrayFromSTLVector()");
00345 
00346   const size_t mFieldSize = stlVec.size();
00347   ARRAY_TYPE retArray(mFieldSize);
00348   for (size_t i=0; i<mFieldSize; ++i){ retArray[i] = stlVec[i]; }
00349   return retArray;
00350 }
00351 
00352 //---------------------------------------------------------------------------
00356 //---------------------------------------------------------------------------
00357 template<typename STL_CONTAINER, typename ITK_ARRAY_TYPE>
00358 const STL_CONTAINER STLVectorFromITKArray(const ITK_ARRAY_TYPE &itkArray)
00359 {
00360   ML_TRACE_IN("template STLVectorFromITKArray()");
00361 
00362   const size_t itkFieldSize = itkArray.size();
00363   STL_CONTAINER stlVector;
00364   for (size_t i=0; i<itkFieldSize; ++i){ stlVector.push_back(itkArray[i]); }
00365   return stlVector;
00366 }
00367 
00368 //---------------------------------------------------------------------------
00380 //---------------------------------------------------------------------------
00381 template<typename INDEX_TYPE>
00382 INDEX_TYPE ITKIndexFromMLVec6(const Vector6 &vec)
00383 {
00384   ML_TRACE_IN("template ITKIndexFromMLVector()");
00385 
00386   INDEX_TYPE sizeObj;
00387   if (sizeObj.GetIndexDimension() > 6){
00388     ML_PRINT_FATAL_ERROR("ITKIndexFromMLVec6", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions.");
00389   }
00390   else{
00391     for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){ sizeObj[i] = vec[i]; }
00392   }
00393   return sizeObj;
00394 }
00395 
00396 
00397 //---------------------------------------------------------------------------
00403 //---------------------------------------------------------------------------
00404 template<class FilterType>
00405 typename FilterType::NodeContainer::Pointer ITKNodeContainerFromBasePointer(Base *baseVal)
00406 {
00407   ML_TRACE_IN("ITKNodeContainerFromBasePointer()");
00408 
00409   XMarkerListContainer *xmlc = NULL;
00410   XMarkerList          *xml  = NULL;
00411   PointList            *pl   = NULL;
00412   VectorList           *vl   = NULL;
00413 
00414   // Get base field.
00415   if (baseVal){
00416     // Check for different base object types.
00417     if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){
00418       xmlc = static_cast<XMarkerListContainer*>(baseVal);
00419     }
00420     else if (ML_BASE_IS_A(baseVal, XMarkerList)){
00421       xml = static_cast<XMarkerList*>(baseVal);
00422     }
00423     else if (ML_BASE_IS_A(baseVal, PointList)){
00424       pl = static_cast<PointList*>(baseVal);
00425     }
00426     else if (ML_BASE_IS_A(baseVal, VectorList)){
00427       vl = static_cast<VectorList*>(baseVal);
00428     }
00429     else{
00430       // No valid type in base field. That can happen.
00431     }
00432   }
00433 
00434   // Get number of points from list.
00435   MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
00436                       (xml  ? static_cast<MLssize_t>(xml->size())             :
00437                       (pl   ? pl->getNum() :
00438                       (vl   ? vl->getNum() : 0))));
00439 
00440 
00441   if (numVals > 0){
00442     // Create a NodeContainer and initialize it.
00443     typename FilterType::NodeContainer::Pointer nc = FilterType::NodeContainer::New();
00444     nc->Initialize();
00445 
00446     // Insert all list elements into the NodeContainer.
00447     for (MLssize_t c=0; c < numVals; ++c){
00448       // Get point list value if we have such a list.
00449       Vector6 plVal(0);
00450       if (pl){
00451         float px=0, py=0, pz=0;
00452         pl->getValue(c, px, py, pz);
00453         plVal[0] = px;
00454         plVal[1] = py;
00455         plVal[2] = pz;
00456       }
00457 
00458       // Get point list value if we have such a list.
00459       Vector6 vlVal(0);
00460       int vecType=0;
00461       if (vl){
00462         float px=0, py=0, pz=0;
00463         vl->getPoint(c, vecType, px, py, pz);
00464         vlVal[0]=px;
00465         vlVal[1]=py;
00466         vlVal[2]=pz;
00467       }
00468 
00469       // get position from any of the lists.
00470       Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
00471                     (xml  ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos             :
00472                     (pl   ? plVal                                            :
00473                     (vl   ? vlVal                                            : Vector6(0))))));
00474 
00475       typename FilterType::NodeType pnt;
00476       pnt.SetValue(0);
00477       pnt.SetIndex(ITKIndexFromMLVec6<ITKML_TYPENAME FilterType::NodeType::IndexType>(mlVec));
00478       nc->InsertElement(c, pnt);
00479     }
00480 
00481     return nc;
00482   }
00483   else{
00484     return NULL;
00485   }
00486 }
00487 
00488 //---------------------------------------------------------------------------
00495 //---------------------------------------------------------------------------
00496 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
00497 typename itk::Matrix<DTYPE, ROW_DIM, COL_DIM> ITKMatrixFromMLMatrix(const Matrix4 &mat)
00498 {
00499   ML_TRACE_IN("ITKMatrixFromMLMatrix()");
00500 
00501   // Create default matrix.
00502   itk::Matrix<DTYPE, ROW_DIM, COL_DIM> retMat;
00503   retMat.SetIdentity();
00504 
00505   // Do not allow more than four dimensions.
00506   int maxRowDim = ROW_DIM;
00507   if (maxRowDim > 4){
00508     maxRowDim = 4;
00509     ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION, "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
00510   }
00511   int maxColDim = COL_DIM;
00512   if (maxColDim > 4){
00513     maxColDim = 4;
00514     ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION, "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
00515   }
00516 
00517   // Copy elements.
00518   for (int row=0; row < maxRowDim; ++row){
00519     for (int col=0; col < maxColDim; ++col){
00520       retMat[row][col] = mat[row][col];
00521     }
00522   }
00523 
00524   return retMat;
00525 }
00526 
00527 //---------------------------------------------------------------------------
00535 //---------------------------------------------------------------------------
00536 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
00537 Matrix4 MLMatrixFromITKMatrix(const ITKML_TYPENAME itk::Matrix<DTYPE, ROW_DIM, COL_DIM> &mat, bool fillWithID=false)
00538 {
00539   ML_TRACE_IN("MLMatrixFromITKMatrix()");
00540 
00541   // Do not allow more than four dimensions.
00542   int maxRowDim = ROW_DIM;
00543   if (maxRowDim > 4){
00544     maxRowDim = 4;
00545     ML_PRINT_WARNING("MLMatrixFromITKMatrix", ML_BAD_DIMENSION, "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
00546   }
00547   int maxColDim = COL_DIM;
00548   if (maxColDim > 4){
00549     maxColDim = 4;
00550     ML_PRINT_WARNING("MLMatrixFromITKMatrix", ML_BAD_DIMENSION, "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
00551   }
00552 
00553   // Copy elements.
00554   Matrix4 retMat;
00555   if (fillWithID){ retMat = Matrix4::getIdentity(); } else { retMat.set(0); }
00556   for (int row=0; row < maxRowDim; ++row){
00557     for (int col=0; col < maxColDim; ++col){
00558       retMat[row][col] = mat[row][col];
00559     }
00560   }
00561 
00562   return retMat;
00563 }
00564 
00565 //---------------------------------------------------------------------------
00571 //---------------------------------------------------------------------------
00572 template<class POINTSETTYPE>
00573 typename POINTSETTYPE::Pointer ITKPointSetFromBasePointer(Base *baseVal)
00574 {
00575   ML_TRACE_IN("ITKPointSetFromBasePointer()");
00576 
00577   XMarkerListContainer *xmlc = NULL;
00578   XMarkerList          *xml  = NULL;
00579   PointList            *pl   = NULL;
00580   VectorList           *vl   = NULL;
00581 
00582   // Get base field.
00583   if (baseVal){
00584     // Check for different base object types.
00585     if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){ xmlc = static_cast<XMarkerListContainer*>(baseVal); }
00586     else if (ML_BASE_IS_A(baseVal, XMarkerList))    { xml  = static_cast<XMarkerList*>(baseVal);          }
00587     else if (ML_BASE_IS_A(baseVal, PointList))      { pl   = static_cast<PointList*>(baseVal);            }
00588     else if (ML_BASE_IS_A(baseVal, VectorList))     { vl   = static_cast<VectorList*>(baseVal);           }
00589     else{ /* No valid type in base field. That can happen. */ }
00590   }
00591 
00592   // Get number of points from list.
00593   MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
00594                       (xml  ? static_cast<MLssize_t>(xml->size())             :
00595                       (pl   ? pl->getNum()                                    :
00596                       (vl   ? vl->getNum()                                    : 0))));
00597 
00598 
00599   // Determine maximum point dimension, clamp it to 6.
00600   int maxDim = POINTSETTYPE::PointDimension;
00601   if (maxDim > 6){
00602     maxDim = 6;
00603     ML_PRINT_WARNING("ITKPointSetFromBasePointer", 
00604                      ML_BAD_DIMENSION, 
00605                      "Too high dimension of ITK PointSet. Only 6 dimensions will be converted.");
00606   }
00607 
00608   if (numVals > 0){
00609 
00610     // Create point set object.
00611     typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
00612 
00613     typedef typename POINTSETTYPE::PointDataContainer DataContainer;
00614     outputPointSet->SetPointData( DataContainer::New());
00615     outputPointSet->GetPoints()->Reserve( numVals );
00616     outputPointSet->GetPointData()->Reserve( numVals );
00617 
00618     typename POINTSETTYPE::PointIdentifier  pointId = 0;
00619     typename POINTSETTYPE::PointType  point;
00620 
00621     // Insert all list elements into the NodeContainer.
00622     for (MLssize_t c=0; c < numVals; ++c){
00623       // Get point list value if we have such a list.
00624       Vector6 plVal(0);
00625       if (pl){
00626         float px=0, py=0, pz=0;
00627         pl->getValue(c, px, py, pz);
00628         plVal[0] = px;
00629         plVal[1] = py;
00630         plVal[2] = pz;
00631       }
00632 
00633       // Get point list value if we have such a list.
00634       Vector6 vlVal(0);
00635       int vecType=0;
00636       if (vl){
00637         float px=0, py=0, pz=0;
00638         vl->getPoint(c, vecType, px, py, pz);
00639         vlVal[0]=px;
00640         vlVal[1]=py;
00641         vlVal[2]=pz;
00642       }
00643 
00644       // get position from any of the lists.
00645       Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
00646                     (xml  ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos             :
00647                     (pl   ? plVal                                                       :
00648                     (vl   ? vlVal                                                       : Vector6(0))))));
00649 
00650       // Copy point components.
00651       for (int j=0; j < maxDim ;j++){ point[j] = mlVec[j]; }
00652       outputPointSet->SetPoint(pointId++, point );
00653     }
00654 
00655     return outputPointSet;
00656   }
00657   else{
00658     // Create and return default (empty) point set object.
00659     typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
00660     return outputPointSet;
00661   }
00662 }
00663 
00664 //---------------------------------------------------------------------------
00668 //---------------------------------------------------------------------------
00669 template <typename ITK_IMPORT_IMAGE_FILTER_TYPE>
00670 void ITKSetOriginFromVec3(itk::ImportImageFilter<typename ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImagePixelType, 
00671                                                  ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImageType::ImageDimension>* importImageFilter, 
00672                           const Vector3 &orig)
00673 {
00674   importImageFilter->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMPORT_IMAGE_FILTER_TYPE::OriginType>(orig,0));
00675 }
00676 
00677 //---------------------------------------------------------------------------
00681 //---------------------------------------------------------------------------
00682 template <typename ITK_IMAGE_TYPE>
00683 void ITKSetOriginFromVec3(itk::Image<typename ITK_IMAGE_TYPE::PixelType, 
00684                                      ITK_IMAGE_TYPE::ImageDimension>* image, 
00685                           const Vector3 &orig)
00686 {
00687   image->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMAGE_TYPE::PointType>(orig,0));
00688 }
00689 
00690 //---------------------------------------------------------------------------
00709 //---------------------------------------------------------------------------
00710 template <typename ITK_CLASS_TYPE>
00711 void setITKWorldFromMedicalImageProperty(MedicalImageProperties props,
00712                                          ITK_CLASS_TYPE *image,
00713                                          bool correctSVS=true)
00714 {
00715   ML_TRACE_IN("template setITKWorldFromMedicalImageProperty()");
00716 
00717   if (!image){ return; }
00718 
00719   // Get ML voxel size/scaling.
00720   const Vector3 scales(props.getVoxelSize());
00721 
00722   // Set voxel spacing, origin and direction cosines of output image and use 1 for unknown higher dimensional components.
00723   image->SetSpacing(ITKVectorFromMLVec3<ITKML_TYPENAME ITK_CLASS_TYPE::SpacingType>(scales, 1));
00724 
00725   // Correct the sub voxel position by translating it to the center.
00726   // In the ML the voxel coordinate is in the corner, in itk and vtk
00727   // it is in the center.
00728   if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3( 0.5, 0.5, 0.5)); }
00729 
00730   Matrix4 mat = props.getVoxelToWorldMatrix();
00731 
00732   // Determine image origin for itk image:
00733   // Extract (sub voxel) corrected translation vector.
00734   const Vector3 orig(mat[0][3], mat[1][3], mat[2][3]);
00735   ITKSetOriginFromVec3<ITK_CLASS_TYPE>(image, orig);
00736   
00737   // Image direction/orientation:
00738   // Multiply mat with inverse voxel scale factor to get normalized direction cosines/orientation matrix.
00739   const Vector3 invScales(MLValueIs0WOM(scales[0]) ? 1 : 1/scales[0],
00740                           MLValueIs0WOM(scales[1]) ? 1 : 1/scales[1],
00741                           MLValueIs0WOM(scales[2]) ? 1 : 1/scales[2]);
00742 
00743   mat[0][0] = mat[0][0]*invScales[0];
00744   mat[1][0] = mat[1][0]*invScales[0];
00745   mat[2][0] = mat[2][0]*invScales[0];
00746   mat[3][0] = 0;
00747 
00748   mat[0][1] = mat[0][1]*invScales[1];
00749   mat[1][1] = mat[1][1]*invScales[1];
00750   mat[2][1] = mat[2][1]*invScales[1];
00751   mat[3][1] = 0;
00752 
00753   mat[0][2] = mat[0][2]*invScales[2];
00754   mat[1][2] = mat[1][2]*invScales[2];
00755   mat[2][2] = mat[2][2]*invScales[2];
00756   mat[3][2] = 0;
00757 
00758   mat[0][3] = 0;
00759   mat[1][3] = 0;
00760   mat[2][3] = 0;
00761   mat[3][3] = 1;
00762 
00763   typename ITK_CLASS_TYPE::DirectionType dirCosines = ITKMatrixFromMLMatrix<MLdouble,
00764                                                                             ITK_CLASS_TYPE::DirectionType::RowDimensions,
00765                                                                             ITK_CLASS_TYPE::DirectionType::ColumnDimensions>(mat);
00766   image->SetDirection(dirCosines);
00767 }
00768 
00769 
00770 //---------------------------------------------------------------------------
00791 //---------------------------------------------------------------------------
00792 template <typename ITK_CLASS_TYPE>
00793 void setMLWorldFromITKScaleOriginAndOrientation(const ITK_CLASS_TYPE *image,
00794                                                 MedicalImageProperties &props,
00795                                                 bool correctSVS=true)
00796 {
00797   ML_TRACE_IN("template setMLWorldFromITKScaleOriginAndOrientation()");
00798 
00799   if (!image){ return; }
00800   if (ITK_CLASS_TYPE::ImageDimension < 2){
00801     ML_PRINT_ERROR("setMLWorldFromITKScaleOriginAndOrientation", 
00802                    ML_BAD_PARAMETER,
00803                    "1 D itk world matrix conversion is not supported; "
00804                    "using identity as return value.");
00805     props.setVoxelToWorldMatrix(Matrix4::getIdentity());
00806   }
00807 
00808   // Get location, voxel scaling and orientation of itk image or importer.
00809   const typename ITK_CLASS_TYPE::SpacingType   spacing   = image->GetSpacing();
00810   const typename ITK_CLASS_TYPE::PointType     origin    = image->GetOrigin();
00811   const typename ITK_CLASS_TYPE::DirectionType direction = image->GetDirection();
00812 
00813   // Copy 3x3 itk matrix components to corresponding ones in id ML matrix.
00814   const Matrix4 dirCosines = MLMatrixFromITKMatrix<double,
00815                                                    ITK_CLASS_TYPE::ImageDimension,
00816                                                    ITK_CLASS_TYPE::ImageDimension>(direction, true);
00817 
00818   // Create the ML world matrix as id and set up scaling, orientation and origin provided by the itk image or importer.
00819   Matrix4 mat = Matrix4::getIdentity();
00820 
00821   // Compose scale, directionCosines and translation to the new ML world matrix.
00822   mat[0][0] = dirCosines[0][0]*spacing[0];
00823   mat[1][0] = dirCosines[1][0]*spacing[0];
00824   mat[2][0] = dirCosines[2][0]*spacing[0];
00825   mat[3][0] = 0;
00826 
00827   mat[0][1] = dirCosines[0][1]*spacing[1];
00828   mat[1][1] = dirCosines[1][1]*spacing[1];
00829   mat[2][1] = dirCosines[2][1]*spacing[1];
00830   mat[3][1] = 0;
00831 
00832   // Avoid invalid accesses to spacing if we operate on 2D images.
00833   const double spacing2 = (ITK_CLASS_TYPE::ImageDimension > 2) ? spacing[2] : 1;
00834   mat[0][2] = dirCosines[0][2]*spacing2;
00835   mat[1][2] = dirCosines[1][2]*spacing2;
00836   mat[2][2] = dirCosines[2][2]*spacing2;
00837   mat[3][2] = 0;
00838 
00839   mat[0][3] = origin[0];
00840   mat[1][3] = origin[1];
00841   mat[2][3] = (ITK_CLASS_TYPE::ImageDimension > 2) ? origin[2] : 0;
00842   mat[3][3] = 1;
00843 
00844   props.setVoxelToWorldMatrix(mat);
00845 
00846   // Subtract half voxel shift - in MedicalImageProperties the matrix considers
00847   // voxel positions at the corner and not in the center.
00848   if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3(-0.5, -0.5, -0.5)); }
00849 }
00850 
00851 
00852 //---------------------------------------------------------------------------
00873 //---------------------------------------------------------------------------
00874 template <typename ITK_INDATATYPE, unsigned int DIM>
00875 typename  itk::ImportImageFilter<ITK_INDATATYPE, DIM>::Pointer getITKImportImageFromSubImg(const SubImage               &inSubImg,
00876                                                                                            const MedicalImageProperties &props,
00877                                                                                            bool                         correctSVS=true)
00878 {
00879   ML_TRACE_IN("template getITKImageFromSubImg()");
00880 
00881   // Create a new ImportImageFilter.
00882   typedef itk::ImportImageFilter<ITK_INDATATYPE, DIM> ImportFilterType;
00883   typedef typename ImportFilterType::Pointer ImportFilterPointerType;
00884 
00885   ImportFilterPointerType importer = ImportFilterType::New();
00886 
00887   // Get box from the input subimage, convert it to a ITK region and
00888   // set it as output image region of the image import filter.
00889   SubImageBox inSubImgBox(inSubImg.getBox());
00890   importer->SetRegion(ITKRegionFromMLSubImgBox<ImportFilterType>(inSubImgBox));
00891 
00892   // Set voxel spacing, origin and orientation of itk image.
00893   setITKWorldFromMedicalImageProperty<ImportFilterType>(props, &(*importer), correctSVS);
00894 
00895   // Set pointer to the data to be imported by the image import filter.
00896   importer->SetImportPointer(static_cast<ITK_INDATATYPE*>(inSubImg.getData()),
00897                              inSubImgBox.getNumVoxels(),
00898                              false); // we don't want to let ITK managing memory
00899   importer->Update();
00900 
00901   // Return the importer object.
00902   return importer;
00903 }
00904 
00905 
00906   //----------------------------------------------------------------------------------
00922   //----------------------------------------------------------------------------------
00923   template <typename RETURN_TYPE_PTR, typename FILTER_TYPE, typename VOXEL_TYPE>
00924   RETURN_TYPE_PTR getInputAsItkImportImageAndSubImg(Module                &op,
00925                                                     int                   inIdx,
00926                                                     TSubImage<VOXEL_TYPE> &dataSubImg,
00927                                                     bool                  correctSVS=true)
00928   {
00929     // Get and load connected image only if it's valid and not a a redirected one
00930     // (which may occur in cases of optional mask image inputs).
00931     PagedImage* pInImg = op.getUpdatedInputImage(inIdx);
00932     if (pInImg){
00933       // Get 3D box input image.
00934       const ImageVector _inImgExt = pInImg->getImageExtent();
00935       const SubImageBox inImgBox(ImageVector(_inImgExt.x, _inImgExt.y, _inImgExt.z,1,1,1));
00936 
00937       // Check whether TSubImage contains enough memory, if not we need to free and reallocate it.
00938       if (dataSubImg.getData() && (dataSubImg.getBox().getExtent() != inImgBox.getExtent())){
00939         dataSubImg.free();
00940       }
00941       // Set up data box and allocate data if still not there.
00942       dataSubImg.setBox(inImgBox);
00943       if (!dataSubImg.getData()){
00944         dataSubImg.allocateAsMemoryBlockHandle(ML_FATAL_MEMORY_ERROR);
00945       }
00946       if (!dataSubImg.getData()){
00947         return NULL;
00948       }
00949 
00950       // Get image data from input.
00951       MLErrorCode err = pInImg->getTile(dataSubImg);
00952       if (ML_RESULT_OK == err){
00953         // Create a new ImportImageFilter.
00954         typename FILTER_TYPE::Pointer importer = FILTER_TYPE::New();
00955 
00956         // Get box from the input subimage, convert it to a ITK region and
00957         // set it as output image region of the image import filter.
00958         importer->SetRegion(ITKRegionFromMLSubImgBox<FILTER_TYPE>(inImgBox));
00959 
00960         // Pass world transformation of ML image to world transformation of itk image or importer.
00961         setITKWorldFromMedicalImageProperty<FILTER_TYPE>(*pInImg, &(*importer), correctSVS);
00962 
00963         // Set pointer to the data to be imported by the image import filter.
00964         // Pass true to make ITK manage the memory, i.e. if the last import object
00965         // disappears the data also disappears.
00966         importer->SetImportPointer(static_cast<VOXEL_TYPE*>(dataSubImg.getData()), inImgBox.getNumVoxels(), false);
00967         importer->Update();
00968         return importer->GetOutput();
00969       }
00970       else{
00971         ML_PRINT_ERROR("mlITKSupportToolFunctions::getInputAsItkImportImageAndSubImg()",
00972                        err,
00973                        "Failed to request input image data, probably subsequent operations will fail");
00974       }
00975     }
00976 
00977     // Error, no image could be loaded.
00978     return NULL;
00979   }
00980 
00981 
00982 ML_END_NAMESPACE
00983 
00984 #endif
00985