From 41f0613451369d8b0d5edf3a26fecc30e948457a Mon Sep 17 00:00:00 2001 From: Axel Garcia Date: Tue, 24 Feb 2026 16:37:47 +0100 Subject: [PATCH] ENH: Improve dynamic casting with error handling to avoid segfault --- .../rtkbackprojections/rtkbackprojections.cxx | 38 ++++-- .../rtkforwardprojections.cxx | 109 +++++++++++++----- include/rtkDrawConeImageFilter.hxx | 7 +- include/rtkImagXGeometryReader.hxx | 34 ++++-- ...rtkIterativeConeBeamReconstructionFilter.h | 68 ++++++++--- src/rtkDigisensGeometryReader.cxx | 68 ++++++++--- src/rtkImagXImageIO.cxx | 60 +++++++--- src/rtkVarianObiGeometryReader.cxx | 60 +++++++--- src/rtkVarianProBeamGeometryReader.cxx | 39 +++++-- src/rtkVarianProBeamXMLFileReader.cxx | 18 +-- src/rtkXRadGeometryReader.cxx | 33 ++++-- 11 files changed, 400 insertions(+), 134 deletions(-) diff --git a/applications/rtkbackprojections/rtkbackprojections.cxx b/applications/rtkbackprojections/rtkbackprojections.cxx index af76124f9..eb14e7d91 100644 --- a/applications/rtkbackprojections/rtkbackprojections.cxx +++ b/applications/rtkbackprojections/rtkbackprojections.cxx @@ -95,6 +95,7 @@ main(int argc, char * argv[]) bp = rtk::FDKBackProjectionImageFilter::New(); break; case (bp_arg_FDKWarpBackProjection): + { if (!args_info.signal_given || !args_info.dvf_given) { std::cerr << "FDKWarpBackProjection requires input 4D deformation " @@ -104,10 +105,17 @@ main(int argc, char * argv[]) def->SetInput(itk::ReadImage(args_info.dvf_arg)); bp = rtk::FDKWarpBackProjectionImageFilter::New(); def->SetSignalFilename(args_info.signal_arg); - dynamic_cast *>( - bp.GetPointer()) - ->SetDeformation(def); + auto * fdkWarp = + dynamic_cast *>( + bp.GetPointer()); + if (fdkWarp == nullptr) + { + std::cerr << "Failed to cast back projection filter to FDKWarpBackProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + fdkWarp->SetDeformation(def); break; + } case (bp_arg_Joseph): bp = rtk::JosephBackProjectionImageFilter::New(); break; @@ -151,11 +159,27 @@ main(int argc, char * argv[]) if (args_info.attenuationmap_given) bp->SetInput(2, attenuationMap); if (args_info.sigmazero_given && args_info.bp_arg == bp_arg_Zeng) - dynamic_cast *>(bp.GetPointer()) - ->SetSigmaZero(args_info.sigmazero_arg); + { + auto * zengBack = + dynamic_cast *>(bp.GetPointer()); + if (zengBack == nullptr) + { + std::cerr << "Failed to cast back projection filter to ZengBackProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + zengBack->SetSigmaZero(args_info.sigmazero_arg); + } if (args_info.alphapsf_given && args_info.bp_arg == bp_arg_Zeng) - dynamic_cast *>(bp.GetPointer()) - ->SetAlpha(args_info.alphapsf_arg); + { + auto * zengBack = + dynamic_cast *>(bp.GetPointer()); + if (zengBack == nullptr) + { + std::cerr << "Failed to cast back projection filter to ZengBackProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + zengBack->SetAlpha(args_info.alphapsf_arg); + } bp->SetGeometry(geometry); TRY_AND_EXIT_ON_ITK_EXCEPTION(bp->Update()) diff --git a/applications/rtkforwardprojections/rtkforwardprojections.cxx b/applications/rtkforwardprojections/rtkforwardprojections.cxx index 486e8d1a7..3ac27a31d 100644 --- a/applications/rtkforwardprojections/rtkforwardprojections.cxx +++ b/applications/rtkforwardprojections/rtkforwardprojections.cxx @@ -117,16 +117,23 @@ main(int argc, char * argv[]) forwardProjection = rtk::MaximumIntensityProjectionImageFilter::New(); break; case (fp_arg_CudaRayCast): + { #ifdef RTK_USE_CUDA forwardProjection = rtk::CudaForwardProjectionImageFilter::New(); - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetStepSize(args_info.step_arg); + auto * cudaForward = dynamic_cast *>( + forwardProjection.GetPointer()); + if (cudaForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to CudaForwardProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + cudaForward->SetStepSize(args_info.step_arg); #else std::cerr << "The program has not been compiled with cuda option" << std::endl; return EXIT_FAILURE; #endif break; + } default: std::cerr << "Unhandled --method value." << std::endl; return EXIT_FAILURE; @@ -139,52 +146,100 @@ main(int argc, char * argv[]) { if (args_info.fp_arg == fp_arg_Joseph) { - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetInferiorClipImage(inferiorClipImage); + auto * josephForward = dynamic_cast *>( + forwardProjection.GetPointer()); + if (josephForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to JosephForwardProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + josephForward->SetInferiorClipImage(inferiorClipImage); } else if (args_info.fp_arg == fp_arg_JosephAttenuated) { - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetInferiorClipImage(inferiorClipImage); + auto * josephAttenuatedForward = + dynamic_cast *>( + forwardProjection.GetPointer()); + if (josephAttenuatedForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to JosephForwardAttenuatedProjectionImageFilter." + << std::endl; + return EXIT_FAILURE; + } + josephAttenuatedForward->SetInferiorClipImage(inferiorClipImage); } else if (args_info.fp_arg == fp_arg_MIP) { - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetInferiorClipImage(inferiorClipImage); + auto * mipForward = dynamic_cast *>( + forwardProjection.GetPointer()); + if (mipForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to MaximumIntensityProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + mipForward->SetInferiorClipImage(inferiorClipImage); } } if (args_info.superiorclipimage_given) { if (args_info.fp_arg == fp_arg_Joseph) { - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetSuperiorClipImage(superiorClipImage); + auto * josephForward = dynamic_cast *>( + forwardProjection.GetPointer()); + if (josephForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to JosephForwardProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + josephForward->SetSuperiorClipImage(superiorClipImage); } else if (args_info.fp_arg == fp_arg_JosephAttenuated) { - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetSuperiorClipImage(superiorClipImage); + auto * josephAttenuatedForward = + dynamic_cast *>( + forwardProjection.GetPointer()); + if (josephAttenuatedForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to JosephForwardAttenuatedProjectionImageFilter." + << std::endl; + return EXIT_FAILURE; + } + josephAttenuatedForward->SetSuperiorClipImage(superiorClipImage); } else if (args_info.fp_arg == fp_arg_MIP) { - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetSuperiorClipImage(superiorClipImage); + auto * mipForward = dynamic_cast *>( + forwardProjection.GetPointer()); + if (mipForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to MaximumIntensityProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + mipForward->SetSuperiorClipImage(superiorClipImage); } } if (args_info.sigmazero_given && args_info.fp_arg == fp_arg_Zeng) - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetSigmaZero(args_info.sigmazero_arg); + { + auto * zengForward = dynamic_cast *>( + forwardProjection.GetPointer()); + if (zengForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to ZengForwardProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + zengForward->SetSigmaZero(args_info.sigmazero_arg); + } if (args_info.alphapsf_given && args_info.fp_arg == fp_arg_Zeng) - dynamic_cast *>( - forwardProjection.GetPointer()) - ->SetAlpha(args_info.alphapsf_arg); + { + auto * zengForward = dynamic_cast *>( + forwardProjection.GetPointer()); + if (zengForward == nullptr) + { + std::cerr << "Failed to cast forward projection filter to ZengForwardProjectionImageFilter." << std::endl; + return EXIT_FAILURE; + } + zengForward->SetAlpha(args_info.alphapsf_arg); + } forwardProjection->SetGeometry(geometry); if (!args_info.lowmem_flag) { diff --git a/include/rtkDrawConeImageFilter.hxx b/include/rtkDrawConeImageFilter.hxx index 1ec0fa9a8..33777bd63 100644 --- a/include/rtkDrawConeImageFilter.hxx +++ b/include/rtkDrawConeImageFilter.hxx @@ -29,7 +29,12 @@ void DrawConeImageFilter::BeforeThreadedGenerateData() { Superclass::BeforeThreadedGenerateData(); - dynamic_cast(this->GetModifiableConvexShape())->SetJ(0.); + auto * quadricShape = dynamic_cast(this->GetModifiableConvexShape()); + if (quadricShape == nullptr) + { + itkExceptionMacro(<< "Failed to cast convex shape to QuadricShape."); + } + quadricShape->SetJ(0.); } } // end namespace rtk diff --git a/include/rtkImagXGeometryReader.hxx b/include/rtkImagXGeometryReader.hxx index 6849e36f1..144527245 100644 --- a/include/rtkImagXGeometryReader.hxx +++ b/include/rtkImagXGeometryReader.hxx @@ -199,7 +199,12 @@ ImagXGeometryReader::GetGeometryForAI2p1() for (const auto & flexmap : list_flexmap) { - std::string str = dynamic_cast(flexmap)->GetText(); + const auto * textNode = dynamic_cast(flexmap); + if (textNode == nullptr) + { + itkExceptionMacro(<< "Unexpected non-text node in flexmap."); + } + std::string str = textNode->GetText(); std::stringstream iss(str); std::vector v; while (iss.good()) @@ -264,7 +269,12 @@ ImagXGeometryReader::GetGeometryForAI1p5() itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(m_ProjectionsFileNames[0].c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode); imageIO = itk::GDCMImageIO::New(); - dynamic_cast(imageIO.GetPointer())->LoadPrivateTagsOn(); + auto * gdcmImageIO = dynamic_cast(imageIO.GetPointer()); + if (gdcmImageIO == nullptr) + { + itkExceptionMacro(<< "Failed to cast ImageIO to GDCMImageIO."); + } + gdcmImageIO->LoadPrivateTagsOn(); // Define, create and set projection reader using ReaderType = itk::ImageFileReader; @@ -276,7 +286,7 @@ ImagXGeometryReader::GetGeometryForAI1p5() // Read room setup parameters in the DICOM info of the first projection std::string roomSetupTagKey = "3001|0012"; std::string roomSetupInfo; - dynamic_cast(imageIO.GetPointer())->GetValueFromTag(roomSetupTagKey, roomSetupInfo); + gdcmImageIO->GetValueFromTag(roomSetupTagKey, roomSetupInfo); // Extract SID, SDD and angle offset from the roomSetupInfo auto parser = itk::DOMNodeXMLReader::New(); @@ -291,7 +301,7 @@ ImagXGeometryReader::GetGeometryForAI1p5() // Read calibration model's parameters in the DICOM info of the first projection std::string calibrationTagKey = "3001|0013"; std::string calibrationInfo; - dynamic_cast(imageIO.GetPointer())->GetValueFromTag(calibrationTagKey, calibrationInfo); + gdcmImageIO->GetValueFromTag(calibrationTagKey, calibrationInfo); // Extract calibration model's parameters from calibrationInfo is.clear(); @@ -473,7 +483,12 @@ ImagXGeometryReader::getAIversion() itk::ImageIOFactory::IOFileModeEnum::ReadMode); imageIO = itk::GDCMImageIO::New(); - dynamic_cast(imageIO.GetPointer())->LoadPrivateTagsOn(); + auto * gdcmImageIO = dynamic_cast(imageIO.GetPointer()); + if (gdcmImageIO == nullptr) + { + itkExceptionMacro(<< "Failed to cast ImageIO to GDCMImageIO."); + } + gdcmImageIO->LoadPrivateTagsOn(); // Define, create and set projection reader using ReaderType = itk::ImageFileReader; @@ -485,7 +500,7 @@ ImagXGeometryReader::getAIversion() // Read room setup parameters in the DICOM info of the first projection std::string AIVersionTagKey = "0018|1020"; std::string AIVersion = ""; - dynamic_cast(imageIO.GetPointer())->GetValueFromTag(AIVersionTagKey, AIVersion); + gdcmImageIO->GetValueFromTag(AIVersionTagKey, AIVersion); return AIVersion; } @@ -551,7 +566,12 @@ ImagXGeometryReader::GenerateData() // Reading Gantry Angle std::string labelId, value; itk::GDCMImageIO::GetLabelFromTag(gantryAngleTag, labelId); - dynamic_cast(imageIO.GetPointer())->GetValueFromTag(gantryAngleTag, value); + auto * gdcmProjectionImageIO = dynamic_cast(imageIO.GetPointer()); + if (gdcmProjectionImageIO == nullptr) + { + itkExceptionMacro(<< "Failed to cast ImageIO to GDCMImageIO for projection " << m_ProjectionsFileName << "."); + } + gdcmProjectionImageIO->GetValueFromTag(gantryAngleTag, value); if (isImagX1p5 || isImagX1p2) // Using CalibModel { diff --git a/include/rtkIterativeConeBeamReconstructionFilter.h b/include/rtkIterativeConeBeamReconstructionFilter.h index ae6a88977..fea39f69a 100644 --- a/include/rtkIterativeConeBeamReconstructionFilter.h +++ b/include/rtkIterativeConeBeamReconstructionFilter.h @@ -245,8 +245,12 @@ class ITK_TEMPLATE_EXPORT IterativeConeBeamReconstructionFilter ForwardProjectionPointerType fw; #ifdef RTK_USE_CUDA fw = CudaForwardProjectionImageFilter::New(); - dynamic_cast *>(fw.GetPointer()) - ->SetStepSize(m_StepSize); + auto * cudaFw = dynamic_cast *>(fw.GetPointer()); + if (cudaFw == nullptr) + { + itkExceptionMacro(<< "Failed to cast forward projector to CudaForwardProjectionImageFilter."); + } + cudaFw->SetStepSize(m_StepSize); #endif return fw; } @@ -269,7 +273,12 @@ class ITK_TEMPLATE_EXPORT IterativeConeBeamReconstructionFilter ForwardProjectionPointerType fw; #ifdef RTK_USE_CUDA fw = CudaWarpForwardProjectionImageFilter::New(); - dynamic_cast(fw.GetPointer())->SetStepSize(m_StepSize); + auto * cudaWarpFw = dynamic_cast(fw.GetPointer()); + if (cudaWarpFw == nullptr) + { + itkExceptionMacro(<< "Failed to cast forward projector to CudaWarpForwardProjectionImageFilter."); + } + cudaWarpFw->SetStepSize(m_StepSize); #endif return fw; } @@ -311,15 +320,25 @@ class ITK_TEMPLATE_EXPORT IterativeConeBeamReconstructionFilter } if (this->GetSuperiorClipImage().IsNotNull()) { - dynamic_cast *>( - fw.GetPointer()) - ->SetSuperiorClipImage(this->GetSuperiorClipImage()); + auto * josephAttenuatedForward = + dynamic_cast *>( + fw.GetPointer()); + if (josephAttenuatedForward == nullptr) + { + itkExceptionMacro(<< "Failed to cast forward projector to JosephForwardAttenuatedProjectionImageFilter."); + } + josephAttenuatedForward->SetSuperiorClipImage(this->GetSuperiorClipImage()); } if (this->GetInferiorClipImage().IsNotNull()) { - dynamic_cast *>( - fw.GetPointer()) - ->SetInferiorClipImage(this->GetInferiorClipImage()); + auto * josephAttenuatedForward = + dynamic_cast *>( + fw.GetPointer()); + if (josephAttenuatedForward == nullptr) + { + itkExceptionMacro(<< "Failed to cast forward projector to JosephForwardAttenuatedProjectionImageFilter."); + } + josephAttenuatedForward->SetInferiorClipImage(this->GetInferiorClipImage()); } return fw; } @@ -343,10 +362,14 @@ class ITK_TEMPLATE_EXPORT IterativeConeBeamReconstructionFilter { fw->SetInput(2, this->GetAttenuationMap()); } - dynamic_cast *>(fw.GetPointer()) - ->SetSigmaZero(m_SigmaZero); - dynamic_cast *>(fw.GetPointer()) - ->SetAlpha(m_AlphaPSF); + auto * zengForward = + dynamic_cast *>(fw.GetPointer()); + if (zengForward == nullptr) + { + itkExceptionMacro(<< "Failed to cast forward projector to ZengForwardProjectionImageFilter."); + } + zengForward->SetSigmaZero(m_SigmaZero); + zengForward->SetAlpha(m_AlphaPSF); return fw; } @@ -400,7 +423,12 @@ class ITK_TEMPLATE_EXPORT IterativeConeBeamReconstructionFilter BackProjectionPointerType bp; #ifdef RTK_USE_CUDA bp = CudaRayCastBackProjectionImageFilter::New(); - dynamic_cast(bp.GetPointer())->SetStepSize(m_StepSize); + auto * cudaRayCastBp = dynamic_cast(bp.GetPointer()); + if (cudaRayCastBp == nullptr) + { + itkExceptionMacro(<< "Failed to cast back projector to CudaRayCastBackProjectionImageFilter."); + } + cudaRayCastBp->SetStepSize(m_StepSize); #endif return bp; } @@ -461,10 +489,14 @@ class ITK_TEMPLATE_EXPORT IterativeConeBeamReconstructionFilter { bp->SetInput(2, this->GetAttenuationMap()); } - dynamic_cast *>(bp.GetPointer()) - ->SetSigmaZero(m_SigmaZero); - dynamic_cast *>(bp.GetPointer()) - ->SetAlpha(m_AlphaPSF); + auto * zengBack = + dynamic_cast *>(bp.GetPointer()); + if (zengBack == nullptr) + { + itkExceptionMacro(<< "Failed to cast back projector to ZengBackProjectionImageFilter."); + } + zengBack->SetSigmaZero(m_SigmaZero); + zengBack->SetAlpha(m_AlphaPSF); return bp; } diff --git a/src/rtkDigisensGeometryReader.cxx b/src/rtkDigisensGeometryReader.cxx index 3ab1fb9b8..1dfee1416 100644 --- a/src/rtkDigisensGeometryReader.cxx +++ b/src/rtkDigisensGeometryReader.cxx @@ -19,6 +19,7 @@ #include "rtkDigisensGeometryReader.h" #include "rtkDigisensGeometryXMLFileReader.h" +#include #include #include #include @@ -42,20 +43,40 @@ rtk::DigisensGeometryReader ::GenerateData() // Getting elements positions using MetaDataVectorType = itk::MetaDataObject; - GeometryType::VectorType rotationAxis = - dynamic_cast(dic["ROTATIONaxis"].GetPointer())->GetMetaDataObjectValue(); - GeometryType::VectorType rotationCenter = - dynamic_cast(dic["ROTATIONcenter"].GetPointer())->GetMetaDataObjectValue(); - GeometryType::VectorType sourcePosition = - dynamic_cast(dic["XRAYsource"].GetPointer())->GetMetaDataObjectValue(); - GeometryType::VectorType detectorPosition = - dynamic_cast(dic["CAMERAreference"].GetPointer())->GetMetaDataObjectValue(); - GeometryType::VectorType detectorNormal = - dynamic_cast(dic["CAMERAnormal"].GetPointer())->GetMetaDataObjectValue(); - GeometryType::VectorType detectorHorizontal = - dynamic_cast(dic["CAMERAhorizontal"].GetPointer())->GetMetaDataObjectValue(); - GeometryType::VectorType detectorVertical = - dynamic_cast(dic["CAMERAvertical"].GetPointer())->GetMetaDataObjectValue(); + auto * rotationAxisMetaData = dynamic_cast(dic["ROTATIONaxis"].GetPointer()); + if (rotationAxisMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"ROTATIONaxis\"."); + GeometryType::VectorType rotationAxis = rotationAxisMetaData->GetMetaDataObjectValue(); + + auto * rotationCenterMetaData = dynamic_cast(dic["ROTATIONcenter"].GetPointer()); + if (rotationCenterMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"ROTATIONcenter\"."); + GeometryType::VectorType rotationCenter = rotationCenterMetaData->GetMetaDataObjectValue(); + + auto * sourcePositionMetaData = dynamic_cast(dic["XRAYsource"].GetPointer()); + if (sourcePositionMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"XRAYsource\"."); + GeometryType::VectorType sourcePosition = sourcePositionMetaData->GetMetaDataObjectValue(); + + auto * detectorPositionMetaData = dynamic_cast(dic["CAMERAreference"].GetPointer()); + if (detectorPositionMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CAMERAreference\"."); + GeometryType::VectorType detectorPosition = detectorPositionMetaData->GetMetaDataObjectValue(); + + auto * detectorNormalMetaData = dynamic_cast(dic["CAMERAnormal"].GetPointer()); + if (detectorNormalMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CAMERAnormal\"."); + GeometryType::VectorType detectorNormal = detectorNormalMetaData->GetMetaDataObjectValue(); + + auto * detectorHorizontalMetaData = dynamic_cast(dic["CAMERAhorizontal"].GetPointer()); + if (detectorHorizontalMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CAMERAhorizontal\"."); + GeometryType::VectorType detectorHorizontal = detectorHorizontalMetaData->GetMetaDataObjectValue(); + + auto * detectorVerticalMetaData = dynamic_cast(dic["CAMERAvertical"].GetPointer()); + if (detectorVerticalMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CAMERAvertical\"."); + GeometryType::VectorType detectorVertical = detectorVerticalMetaData->GetMetaDataObjectValue(); // Check assumptions if (sourcePosition[0] != 0. || sourcePosition[1] != 0. || detectorNormal[0] != 0. || detectorNormal[1] != 0. || @@ -87,11 +108,20 @@ rtk::DigisensGeometryReader ::GenerateData() double projectionOffsetY = detectorPosition[1] * detectorVertical[1]; // Rotation - double startAngle = - dynamic_cast(dic["RADIOSstartAngle"].GetPointer())->GetMetaDataObjectValue(); - double angularRange = - dynamic_cast(dic["RADIOSangularRange"].GetPointer())->GetMetaDataObjectValue(); - int nProj = dynamic_cast(dic["RADIOSNumberOfFiles"].GetPointer())->GetMetaDataObjectValue(); + auto * startAngleMetaData = dynamic_cast(dic["RADIOSstartAngle"].GetPointer()); + if (startAngleMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"RADIOSstartAngle\"."); + const double startAngle = startAngleMetaData->GetMetaDataObjectValue(); + + auto * angularRangeMetaData = dynamic_cast(dic["RADIOSangularRange"].GetPointer()); + if (angularRangeMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"RADIOSangularRange\"."); + const double angularRange = angularRangeMetaData->GetMetaDataObjectValue(); + + auto * nProjMetaData = dynamic_cast(dic["RADIOSNumberOfFiles"].GetPointer()); + if (nProjMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"RADIOSNumberOfFiles\"."); + const int nProj = nProjMetaData->GetMetaDataObjectValue(); for (int i = 0; i < nProj; i++) { // Convert rotation center and rotation axis parameterization to euler angles diff --git a/src/rtkImagXImageIO.cxx b/src/rtkImagXImageIO.cxx index 34b286dc9..970ca27fd 100644 --- a/src/rtkImagXImageIO.cxx +++ b/src/rtkImagXImageIO.cxx @@ -20,6 +20,7 @@ #include "rtkImagXXMLFileReader.h" #include +#include #include #include #include @@ -41,8 +42,10 @@ rtk::ImagXImageIO::ReadImageInformation() using MetaDataDoubleType = itk::MetaDataObject; using MetaDataStringType = itk::MetaDataObject; using MetaDataIntType = itk::MetaDataObject; - - std::string pixelType = dynamic_cast(dic["pixelFormat"].GetPointer())->GetMetaDataObjectValue(); + auto * pixelTypeMetaData = dynamic_cast(dic["pixelFormat"].GetPointer()); + if (pixelTypeMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"pixelFormat\"."); + std::string pixelType = pixelTypeMetaData->GetMetaDataObjectValue(); if (pixelType == "Type_uint8") SetComponentType(itk::ImageIOBase::IOComponentEnum::UCHAR); if (pixelType == "Type_sint8") @@ -61,19 +64,42 @@ rtk::ImagXImageIO::ReadImageInformation() if (dic["dimensions"].GetPointer() == nullptr) SetNumberOfDimensions(3); else - SetNumberOfDimensions((dynamic_cast(dic["dimensions"].GetPointer())->GetMetaDataObjectValue())); + { + auto * dimensionsMetaData = dynamic_cast(dic["dimensions"].GetPointer()); + if (dimensionsMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"dimensions\"."); + SetNumberOfDimensions(dimensionsMetaData->GetMetaDataObjectValue()); + } - SetDimensions(0, dynamic_cast(dic["x"].GetPointer())->GetMetaDataObjectValue()); - SetSpacing(0, dynamic_cast(dic["spacing_x"].GetPointer())->GetMetaDataObjectValue()); + auto * xMetaData = dynamic_cast(dic["x"].GetPointer()); + if (xMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"x\"."); + SetDimensions(0, xMetaData->GetMetaDataObjectValue()); + auto * spacingXMetaData = dynamic_cast(dic["spacing_x"].GetPointer()); + if (spacingXMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"spacing_x\"."); + SetSpacing(0, spacingXMetaData->GetMetaDataObjectValue()); if (GetNumberOfDimensions() > 1) { - SetDimensions(1, dynamic_cast(dic["y"].GetPointer())->GetMetaDataObjectValue()); - SetSpacing(1, dynamic_cast(dic["spacing_y"].GetPointer())->GetMetaDataObjectValue()); + auto * yMetaData = dynamic_cast(dic["y"].GetPointer()); + if (yMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"y\"."); + SetDimensions(1, yMetaData->GetMetaDataObjectValue()); + auto * spacingYMetaData = dynamic_cast(dic["spacing_y"].GetPointer()); + if (spacingYMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"spacing_y\"."); + SetSpacing(1, spacingYMetaData->GetMetaDataObjectValue()); } if (GetNumberOfDimensions() > 2) { - SetDimensions(2, dynamic_cast(dic["z"].GetPointer())->GetMetaDataObjectValue()); - SetSpacing(2, dynamic_cast(dic["spacing_z"].GetPointer())->GetMetaDataObjectValue()); + auto * zMetaData = dynamic_cast(dic["z"].GetPointer()); + if (zMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"z\"."); + SetDimensions(2, zMetaData->GetMetaDataObjectValue()); + auto * spacingZMetaData = dynamic_cast(dic["spacing_z"].GetPointer()); + if (spacingZMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"spacing_z\"."); + SetSpacing(2, spacingZMetaData->GetMetaDataObjectValue()); if (GetSpacing(2) == 0) SetSpacing(2, 1); } @@ -83,8 +109,10 @@ rtk::ImagXImageIO::ReadImageInformation() matrix.SetIdentity(); else { - std::istringstream iss( - dynamic_cast(dic["matrixTransform"].GetPointer())->GetMetaDataObjectValue()); + auto * matrixTransformMetaData = dynamic_cast(dic["matrixTransform"].GetPointer()); + if (matrixTransformMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"matrixTransform\"."); + std::istringstream iss(matrixTransformMetaData->GetMetaDataObjectValue()); for (unsigned int j = 0; j < 4; j++) for (unsigned int i = 0; i < 4; i++) iss >> matrix[j][i]; @@ -101,7 +129,10 @@ rtk::ImagXImageIO::ReadImageInformation() SetOrigin(i, matrix[i][3]); } - if (std::string("LSB") == dynamic_cast(dic["byteOrder"].GetPointer())->GetMetaDataObjectValue()) + auto * byteOrderMetaData = dynamic_cast(dic["byteOrder"].GetPointer()); + if (byteOrderMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"byteOrder\"."); + if (std::string("LSB") == byteOrderMetaData->GetMetaDataObjectValue()) this->SetByteOrder(IOByteOrderEnum::LittleEndian); else this->SetByteOrder(IOByteOrderEnum::BigEndian); @@ -110,7 +141,10 @@ rtk::ImagXImageIO::ReadImageInformation() m_RawFileName = itksys::SystemTools::GetFilenamePath(m_FileName); if (!m_RawFileName.empty()) m_RawFileName += std::string("/"); - m_RawFileName += dynamic_cast(dic["rawFile"].GetPointer())->GetMetaDataObjectValue(); + auto * rawFileMetaData = dynamic_cast(dic["rawFile"].GetPointer()); + if (rawFileMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"rawFile\"."); + m_RawFileName += rawFileMetaData->GetMetaDataObjectValue(); } //// //-------------------------------------------------------------------- diff --git a/src/rtkVarianObiGeometryReader.cxx b/src/rtkVarianObiGeometryReader.cxx index 758f5313a..5e17675b0 100644 --- a/src/rtkVarianObiGeometryReader.cxx +++ b/src/rtkVarianObiGeometryReader.cxx @@ -25,6 +25,8 @@ #include "rtkHncImageIOFactory.h" #include +#include +#include #include rtk::VarianObiGeometryReader ::VarianObiGeometryReader() @@ -46,27 +48,52 @@ rtk::VarianObiGeometryReader ::GenerateData() // Constants used to generate projection matrices itk::MetaDataDictionary & dic = *(obiXmlReader->GetOutputObject()); using MetaDataDoubleType = itk::MetaDataObject; - const double sdd = dynamic_cast(dic["CalibratedSID"].GetPointer())->GetMetaDataObjectValue(); - const double sid = dynamic_cast(dic["CalibratedSAD"].GetPointer())->GetMetaDataObjectValue(); + auto * sddMetaData = dynamic_cast(dic["CalibratedSID"].GetPointer()); + if (sddMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CalibratedSID\"."); + const double sdd = sddMetaData->GetMetaDataObjectValue(); - double offsetx = NAN; - std::string fanType = - dynamic_cast *>(dic["FanType"].GetPointer())->GetMetaDataObjectValue(); + auto * sidMetaData = dynamic_cast(dic["CalibratedSAD"].GetPointer()); + if (sidMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CalibratedSAD\"."); + const double sid = sidMetaData->GetMetaDataObjectValue(); + + double offsetx = NAN; + auto * fanTypeMetaData = dynamic_cast *>(dic["FanType"].GetPointer()); + if (fanTypeMetaData == nullptr) + { + itkExceptionMacro(<< "Missing or invalid metadata \"FanType\"."); + } + std::string fanType = fanTypeMetaData->GetMetaDataObjectValue(); if (itksys::SystemTools::Strucmp(fanType.c_str(), "HalfFan") == 0) { // Half Fan (offset detector), get lateral offset from XML file - offsetx = - dynamic_cast(dic["CalibratedDetectorOffsetX"].GetPointer())->GetMetaDataObjectValue() + - dynamic_cast(dic["DetectorPosLat"].GetPointer())->GetMetaDataObjectValue(); + auto * calibratedDetectorOffsetXMetaData = + dynamic_cast(dic["CalibratedDetectorOffsetX"].GetPointer()); + if (calibratedDetectorOffsetXMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CalibratedDetectorOffsetX\"."); + const double calibratedDetectorOffsetX = calibratedDetectorOffsetXMetaData->GetMetaDataObjectValue(); + + auto * detectorPosLatMetaData = dynamic_cast(dic["DetectorPosLat"].GetPointer()); + if (detectorPosLatMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"DetectorPosLat\"."); + const double detectorPosLat = detectorPosLatMetaData->GetMetaDataObjectValue(); + + offsetx = calibratedDetectorOffsetX + detectorPosLat; } else { // Full Fan (centered detector) - offsetx = - dynamic_cast(dic["CalibratedDetectorOffsetX"].GetPointer())->GetMetaDataObjectValue(); + auto * calibratedDetectorOffsetXMetaData = + dynamic_cast(dic["CalibratedDetectorOffsetX"].GetPointer()); + if (calibratedDetectorOffsetXMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CalibratedDetectorOffsetX\"."); + offsetx = calibratedDetectorOffsetXMetaData->GetMetaDataObjectValue(); } - const double offsety = - dynamic_cast(dic["CalibratedDetectorOffsetY"].GetPointer())->GetMetaDataObjectValue(); + auto * offsetYMetaData = dynamic_cast(dic["CalibratedDetectorOffsetY"].GetPointer()); + if (offsetYMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"CalibratedDetectorOffsetY\"."); + const double offsety = offsetYMetaData->GetMetaDataObjectValue(); // Projections reader (for angle) rtk::HndImageIOFactory::RegisterOneFactory(); @@ -80,9 +107,12 @@ rtk::VarianObiGeometryReader ::GenerateData() reader->SetFileName(projectionsFileName); reader->UpdateOutputInformation(); - const double angle = - dynamic_cast(reader->GetMetaDataDictionary()["dCTProjectionAngle"].GetPointer()) - ->GetMetaDataObjectValue(); + itk::MetaDataDictionary & projectionDic = reader->GetMetaDataDictionary(); + auto * angleMetaData = dynamic_cast(projectionDic["dCTProjectionAngle"].GetPointer()); + if (angleMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"dCTProjectionAngle\" in projection " << projectionsFileName + << "."); + const double angle = angleMetaData->GetMetaDataObjectValue(); m_Geometry->AddProjection(sid, sdd, angle, offsetx, offsety); } diff --git a/src/rtkVarianProBeamGeometryReader.cxx b/src/rtkVarianProBeamGeometryReader.cxx index 281d59235..3ef5ff428 100644 --- a/src/rtkVarianProBeamGeometryReader.cxx +++ b/src/rtkVarianProBeamGeometryReader.cxx @@ -22,6 +22,8 @@ #include "rtkXimImageIOFactory.h" #include +#include +#include #include rtk::VarianProBeamGeometryReader ::VarianProBeamGeometryReader() @@ -43,8 +45,15 @@ rtk::VarianProBeamGeometryReader ::GenerateData() // Constants used to generate projection matrices itk::MetaDataDictionary & dic = *(proBeamXmlReader->GetOutputObject()); using MetaDataDoubleType = itk::MetaDataObject; - const double sdd = dynamic_cast(dic["SID"].GetPointer())->GetMetaDataObjectValue(); - const double sid = dynamic_cast(dic["SAD"].GetPointer())->GetMetaDataObjectValue(); + auto * sddMetaData = dynamic_cast(dic["SID"].GetPointer()); + if (sddMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"SID\"."); + const double sdd = sddMetaData->GetMetaDataObjectValue(); + + auto * sidMetaData = dynamic_cast(dic["SAD"].GetPointer()); + if (sidMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"SAD\"."); + const double sid = sidMetaData->GetMetaDataObjectValue(); // Projections reader (for angle) rtk::XimImageIOFactory::RegisterOneFactory(); @@ -56,19 +65,27 @@ rtk::VarianProBeamGeometryReader ::GenerateData() reader->SetFileName(projectionsFileName); reader->UpdateOutputInformation(); - const double angle = - dynamic_cast(reader->GetMetaDataDictionary()["dCTProjectionAngle"].GetPointer()) - ->GetMetaDataObjectValue(); + itk::MetaDataDictionary & projectionDic = reader->GetMetaDataDictionary(); + auto * angleMetaData = dynamic_cast(projectionDic["dCTProjectionAngle"].GetPointer()); + if (angleMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"dCTProjectionAngle\" in projection " << projectionsFileName + << "."); + const double angle = angleMetaData->GetMetaDataObjectValue(); if (angle != 6000) { /* Warning: The offsets in the test scans were very small, however this configuration improved reconstruction quality slightly.*/ - const double offsetx = - dynamic_cast(reader->GetMetaDataDictionary()["dDetectorOffsetX"].GetPointer()) - ->GetMetaDataObjectValue(); - const double offsety = - dynamic_cast(reader->GetMetaDataDictionary()["dDetectorOffsetY"].GetPointer()) - ->GetMetaDataObjectValue(); + auto * offsetXMetaData = dynamic_cast(projectionDic["dDetectorOffsetX"].GetPointer()); + if (offsetXMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"dDetectorOffsetX\" in projection " << projectionsFileName + << "."); + const double offsetx = offsetXMetaData->GetMetaDataObjectValue(); + + auto * offsetYMetaData = dynamic_cast(projectionDic["dDetectorOffsetY"].GetPointer()); + if (offsetYMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"dDetectorOffsetY\" in projection " << projectionsFileName + << "."); + const double offsety = offsetYMetaData->GetMetaDataObjectValue(); /*The angle-direction of RTK is opposite of the Xim properties (There doesn't seem to be a flag for direction in neither the xml nor xim file) */ m_Geometry->AddProjection(sid, sdd, 180.0 - angle, offsetx, offsety); diff --git a/src/rtkVarianProBeamXMLFileReader.cxx b/src/rtkVarianProBeamXMLFileReader.cxx index 5de643a66..db7e41149 100644 --- a/src/rtkVarianProBeamXMLFileReader.cxx +++ b/src/rtkVarianProBeamXMLFileReader.cxx @@ -57,14 +57,16 @@ VarianProBeamXMLFileReader::EndElement(const char * name) itk::EncapsulateMetaData(m_Dictionary, encapsulatedName, d); \ } -#define MODIFY_META_DATA_DOUBLE_MULTIPLY(metaName, encapsulatedName) \ - if (itksys::SystemTools::Strucmp(name, metaName) == 0) \ - { \ - double d = std::stod(m_CurCharacterData.c_str()); \ - using MetaDataDoubleType = itk::MetaDataObject; \ - const double multiplier = \ - dynamic_cast(m_Dictionary[encapsulatedName].GetPointer())->GetMetaDataObjectValue(); \ - itk::EncapsulateMetaData(m_Dictionary, encapsulatedName, d * multiplier); \ +#define MODIFY_META_DATA_DOUBLE_MULTIPLY(metaName, encapsulatedName) \ + if (itksys::SystemTools::Strucmp(name, metaName) == 0) \ + { \ + double d = std::stod(m_CurCharacterData.c_str()); \ + using MetaDataDoubleType = itk::MetaDataObject; \ + auto * metaDataObject = dynamic_cast(m_Dictionary[encapsulatedName].GetPointer()); \ + if (metaDataObject == nullptr) \ + itkGenericExceptionMacro(<< "Missing or invalid metadata \"" << encapsulatedName << "\" while reading \"" \ + << metaName << "\"."); \ + itk::EncapsulateMetaData(m_Dictionary, encapsulatedName, d * metaDataObject->GetMetaDataObjectValue()); \ } #define ENCAPLULATE_META_DATA_STRING(metaName) \ diff --git a/src/rtkXRadGeometryReader.cxx b/src/rtkXRadGeometryReader.cxx index ea56b9686..42ff18086 100644 --- a/src/rtkXRadGeometryReader.cxx +++ b/src/rtkXRadGeometryReader.cxx @@ -21,6 +21,7 @@ #include "rtkXRadImageIOFactory.h" #include +#include #include rtk::XRadGeometryReader ::XRadGeometryReader() @@ -54,15 +55,25 @@ rtk::XRadGeometryReader ::GenerateData() sectionName = os.str(); paramName = sectionName + "_CBCT.ProjectionGeometryArray.u_axis"; - std::istringstream isu(dynamic_cast(dic[paramName].GetPointer())->GetMetaDataObjectValue()); + auto * uAxisMetaData = dynamic_cast(dic[paramName].GetPointer()); + if (uAxisMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"" << paramName << "\"."); + std::istringstream isu(uAxisMetaData->GetMetaDataObjectValue()); paramName = sectionName + "_CBCT.ProjectionGeometryArray.v_axis"; - std::istringstream isv(dynamic_cast(dic[paramName].GetPointer())->GetMetaDataObjectValue()); + auto * vAxisMetaData = dynamic_cast(dic[paramName].GetPointer()); + if (vAxisMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"" << paramName << "\"."); + std::istringstream isv(vAxisMetaData->GetMetaDataObjectValue()); paramName = sectionName + "_CBCT.ProjectionGeometryArray.focus"; - std::istringstream isfocus( - dynamic_cast(dic[paramName].GetPointer())->GetMetaDataObjectValue()); + auto * focusMetaData = dynamic_cast(dic[paramName].GetPointer()); + if (focusMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"" << paramName << "\"."); + std::istringstream isfocus(focusMetaData->GetMetaDataObjectValue()); paramName = sectionName + "_CBCT.ProjectionGeometryArray.center"; - std::istringstream iscenter( - dynamic_cast(dic[paramName].GetPointer())->GetMetaDataObjectValue()); + auto * centerMetaData = dynamic_cast(dic[paramName].GetPointer()); + if (centerMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"" << paramName << "\"."); + std::istringstream iscenter(centerMetaData->GetMetaDataObjectValue()); itk::Vector u, v; itk::Vector focus, center; for (unsigned int j = 0; j < 3; j++) @@ -99,11 +110,17 @@ rtk::XRadGeometryReader ::GenerateData() tmpGeo->AddProjection(&(focus[0]), &(center[0]), u, v); paramName = sectionName + "_CBCT.ProjectionGeometryArray.u_off"; - std::string suoff = dynamic_cast(dic[paramName].GetPointer())->GetMetaDataObjectValue(); + auto * uOffsetMetaData = dynamic_cast(dic[paramName].GetPointer()); + if (uOffsetMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"" << paramName << "\"."); + std::string suoff = uOffsetMetaData->GetMetaDataObjectValue(); double uoff = std::stod(suoff.c_str()) * reader->GetSpacing(0); paramName = sectionName + "_CBCT.ProjectionGeometryArray.v_off"; - std::string svoff = dynamic_cast(dic[paramName].GetPointer())->GetMetaDataObjectValue(); + auto * vOffsetMetaData = dynamic_cast(dic[paramName].GetPointer()); + if (vOffsetMetaData == nullptr) + itkExceptionMacro(<< "Missing or invalid metadata \"" << paramName << "\"."); + std::string svoff = vOffsetMetaData->GetMetaDataObjectValue(); double voff = std::stod(svoff.c_str()) * reader->GetSpacing(1); m_Geometry->AddProjectionInRadians(tmpGeo->GetSourceToIsocenterDistances()[i],