7474#include " AffineTransformHelper.h"
7575#include " InputSelectionImageFilter.h"
7676#include " MetaDataAccess.h"
77+ #include " AllPurposeProgressAccumulator.h"
7778
7879#include < vnl/vnl_inverse.h>
7980#include < iostream>
@@ -2371,6 +2372,39 @@ ::ExtractROI(const SNAPSegmentationROISettings &roi,
23712372 return retptr;
23722373}
23732374
2375+ template <class TTraits , class TBase >
2376+ SmartPtr<ImageWrapperBase>
2377+ ImageWrapper<TTraits,TBase>
2378+ ::ExtractROI4D (const SNAPSegmentationROISettings &roi,
2379+ itk::Command *progressCommand) const
2380+ {
2381+ Image4DPointer newImage = this ->DeepCopyRegion4D (roi, progressCommand);
2382+
2383+ // Initialize the new wrapper
2384+ typedef typename TTraits::WrapperType WrapperType;
2385+ SmartPtr<WrapperType> newWrapper = WrapperType::New ();
2386+
2387+ // Copy the display to anatomy geometry to the new wrapper
2388+ IRISDisplayGeometry temp = m_DisplayGeometry;
2389+ newWrapper->SetDisplayGeometry (temp);
2390+
2391+ // Assign the new image to the new wrapper
2392+ newWrapper->SetImage4D (newImage);
2393+ newWrapper->SetNativeMapping (this ->GetNativeMapping ());
2394+
2395+ // Appropriate the default nickname?
2396+ newWrapper->SetDefaultNickname (this ->GetDefaultNickname ());
2397+ newWrapper->SetAlpha (this ->GetAlpha ());
2398+ newWrapper->SetSticky (this ->IsSticky ());
2399+
2400+ // We should not copy the user-assigned metadata. It's up to the
2401+ // user what should propagate to the ROI
2402+
2403+ // Cast to base class
2404+ SmartPtr<ImageWrapperBase> retptr = newWrapper.GetPointer ();
2405+ return retptr;
2406+ }
2407+
23742408
23752409template <class TTraits , class TBase >
23762410typename ImageWrapper<TTraits,TBase>::ImagePointer
@@ -2391,6 +2425,85 @@ ::DeepCopyRegion(const SNAPSegmentationROISettings &roi,
23912425 force_resampling, progressCommand);
23922426}
23932427
2428+ template <class TTraits , class TBase >
2429+ typename ImageWrapper<TTraits,TBase>::Image4DPointer
2430+ ImageWrapper<TTraits,TBase>
2431+ ::DeepCopyRegion4D (const SNAPSegmentationROISettings &roi,
2432+ itk::Command *progressCommand) const
2433+ {
2434+ // If the image in this wrapper is not the same as the reference space,
2435+ // we must force resampling to occur
2436+ bool force_resampling = !this ->IsSlicingOrthogonal ();
2437+
2438+ Image4DPointer outImg = Image4DType::New ();
2439+ const unsigned int nT = this ->GetNumberOfTimePoints ();
2440+
2441+ // Set the spacing, origin, direction for the last coordinate
2442+ auto spacing_4d = m_Image4D->GetSpacing ();
2443+ auto origin_4d = m_Image4D->GetOrigin ();
2444+ auto dir_4d = m_Image4D->GetDirection ();
2445+ auto region_4d = m_Image4D->GetBufferedRegion ();
2446+
2447+ // Create a 4d buffer
2448+ typedef typename Image4DType::PixelContainer::Element ElementType;
2449+ typedef typename Image4DType::PixelContainer::ElementIdentifier ElementIdType;
2450+ auto size_3d = roi.GetROI ().GetSize ();
2451+ auto nC = m_Image4D->GetNumberOfComponentsPerPixel ();
2452+ ElementIdType buffer3dSize = size_3d[0 ] * size_3d[1 ] * size_3d[2 ] * nC;
2453+ ElementIdType buffer3dSizeInBytes = buffer3dSize * sizeof (ElementType);
2454+ ElementIdType buffer4dSize = buffer3dSize * nT;
2455+ ElementType *buffer4d = new ElementType[buffer4dSize];
2456+ ElementType *pCrntTPStart = buffer4d; // starting mem location of the current tp
2457+
2458+ typedef ImageWrapperPartialSpecializationTraits<ImageType, Image4DType> Specialization;
2459+
2460+ // Prepare progress accumulation
2461+ SmartPtr<AllPurposeProgressAccumulator> progress = AllPurposeProgressAccumulator::New ();
2462+ progress->AddObserver (itk::ProgressEvent (), progressCommand);
2463+ typedef AllPurposeProgressAccumulator::CommandPointer CmdPtr;
2464+ std::vector<CmdPtr> TPCommand;
2465+
2466+ for (unsigned int t = 0u ; t < nT; ++t)
2467+ {
2468+ TPCommand.push_back (progress->RegisterITKSourceViaCommand (1 ));
2469+ }
2470+
2471+ typename ImageType::Pointer tpResliced, tpImg;
2472+
2473+ for (unsigned int t = 0u ; t < nT; ++t)
2474+ {
2475+ tpImg = this ->GetImageByTimePoint (t);
2476+ tpResliced = Specialization::CopyRegion (tpImg, m_ReferenceSpace, this ->GetITKTransform (),
2477+ roi, force_resampling, TPCommand[t]);
2478+
2479+ auto buffer3d = tpResliced->GetPixelContainer ()->GetBufferPointer ();
2480+ memcpy (pCrntTPStart, buffer3d, buffer3dSizeInBytes);
2481+ pCrntTPStart += buffer3dSize; // Increment pointer to next tp start
2482+ }
2483+
2484+ // use the last resliced tp image to configure the output origin/spacing/direction/region
2485+ // -- this only configures the first three dimensions
2486+ for (int j = 0 ; j < 3 ; ++j)
2487+ {
2488+ region_4d.SetIndex (j, tpResliced->GetBufferedRegion ().GetIndex (j));
2489+ region_4d.SetSize (j, tpResliced->GetBufferedRegion ().GetSize (j));
2490+ spacing_4d[j] = tpResliced->GetSpacing ()[j];
2491+ origin_4d[j] = tpResliced->GetOrigin ()[j];
2492+ for (unsigned int k = 0 ; k < 3 ; k++)
2493+ dir_4d (j,k) = tpResliced->GetDirection () (j,k);
2494+ }
2495+
2496+ outImg->SetRegions (region_4d);
2497+ outImg->SetSpacing (spacing_4d);
2498+ outImg->SetOrigin (origin_4d);
2499+ outImg->SetDirection (dir_4d);
2500+ outImg->SetNumberOfComponentsPerPixel (tpResliced->GetNumberOfComponentsPerPixel ());
2501+
2502+ // set the constructed 4d buffer to output's pixel container
2503+ outImg->GetPixelContainer ()->SetImportPointer (buffer4d, buffer4dSize, true );
2504+ return outImg;
2505+ }
2506+
23942507
23952508
23962509
0 commit comments