/*============================================================================= NOTE: THIS FILE IS A HANDMADE WRAPPER FOR THE ManagedITK PROJECT. Project: ManagedITK Program: Insight Segmentation & Registration Toolkit Module: itkManagedImage.cxx Language: C++/CLI Author: Dan Mueller $Date: 2007-06-26 16:03:48 +1000 (Tue, 26 Jun 2007) $ $Revision: 176 $ Copyright (c) Queensland University of Technology (QUT) 2007. All rights reserved. Portions of this code are covered under the ITK and VTK copyright. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm 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. =============================================================================*/ #pragma once #pragma warning( disable : 4635 ) // Disable warnings about XML doc comments #pragma warning( disable : 4996 ) // Disable warnings about deprecated methods #ifndef __itkManagedImage_cxx #define __itkManagedImage_cxx // Include some useful ManagedITK files #include "itkManagedImageBase.cxx" #include "itkManagedInvalidWrappedTypeException.cxx" // Use some managed namespaces #using #using using namespace System; using namespace System::IO; using namespace System::Reflection; using namespace System::Diagnostics; namespace itk { /// ///This class is a managed wrapper for itk::Image. A specific image type ///(eg. unsigned char, float, etc.) can be instantiated using the ///New(pixeltype, dim) method. /// /// ///Images are defined by a pixel type (modeling the dependent variables), ///and a dimension (number of independent variables). ///An image is modeled as an array, defined by a start index and a size. ///The underlying array can be accessed via the Buffer property. /// ///There are three sets of meta-data describing an image. These are "Region" ///objects that define a portion of an image via a starting index for the image ///array and a size. The ivar LargestPossibleRegion defines the size and ///starting index of the image dataset. The entire image dataset, however, ///need not be resident in memory. The region of the image that is resident in ///memory is defined by the "BufferedRegion". The Buffer is a contiguous block ///of memory. The third set of meta-data defines a region of interest, called ///the "RequestedRegion". The RequestedRegion is used by the pipeline ///execution model to define what a filter is requested to produce. /// public ref class itkImage : itkImageBase { private: itkImageBase^ m_Instance; protected: ///Protected constructor. itkImage ( ) : itkImageBase( ) { } public: ///Dispose of the managed object. ~itkImage ( ) { if (!this->m_IsDisposed) { try { delete m_Instance; } catch ( ... ) { } finally { this->m_IsDisposed = true; } } } ///Finalize the managed object. !itkImage ( ) { if (!this->m_IsDisposed) delete this; } ///Get/set a string describing the data object (typically an abosolute file name). property String^ Name { virtual String^ get() override { return this->m_Instance->Name; } virtual void set( String^ name ) override { this->m_Instance->Name = name; } } ///Get the size of the image (from the LargestPossibleRegion). ///This method was added in ManagedITK for simplicity. property itkSize^ Size { virtual itkSize^ get() override { return this->m_Instance->Size; } } ///Get/set the spacing between pixles of the image. property itkSpacing^ Spacing { virtual itkSpacing^ get() override { return this->m_Instance->Spacing; } virtual void set( itkSpacing^ spacing ) override { this->m_Instance->Spacing = spacing; } } ///Get/set the origin of the image in physical space. property itkPoint^ Origin { virtual itkPoint^ get() override { return this->m_Instance->Origin; } virtual void set( itkPoint^ origin ) override { this->m_Instance->Origin = origin; } } /// ///Get/set the region object that defines the size and starting index ///for the largest possible region this image could represent. /// property itkImageRegion^ LargestPossibleRegion { virtual itkImageRegion^ get() override { return this->m_Instance->LargestPossibleRegion; } virtual void set ( itkImageRegion^ region ) override { this->m_Instance->LargestPossibleRegion = region; } } /// ///Get/set the region object that defines the size and starting index ///for the region of the image requested (i.e., the region of the ///image to be operated on by a filter). Setting the RequestedRegion ///does not cause the object to be modified. /// property itkImageRegion^ RequestedRegion { virtual itkImageRegion^ get() override { return this->m_Instance->RequestedRegion; } virtual void set ( itkImageRegion^ region ) override { this->m_Instance->RequestedRegion = region; } } /// ///Get/set the region object that defines the size and starting index ///of the region of the image currently loaded in memory. /// property itkImageRegion^ BufferedRegion { virtual itkImageRegion^ get() override { return this->m_Instance->BufferedRegion; } virtual void set ( itkImageRegion^ region ) override { this->m_Instance->BufferedRegion = region; } } ///Get the pointer to the underlying image data array. property IntPtr Buffer { virtual IntPtr get() override { return this->m_Instance->Buffer; } } ///Get the direction cosines of the image. The direction cosines are vectors that point from one pixel to the next. property itkMatrix^ Direction { virtual itkMatrix^ get() override { return this->m_Instance->Direction; } virtual void set ( itkMatrix^ direction ) override { this->m_Instance->Direction = direction; } } ///Get the last modified time. property unsigned long MTime { virtual unsigned long get() override { return this->m_Instance->MTime; } } ///Get a string representing the type instance of this INativePointer. ///"IUC2", "IF3", "IVF22". property String^ MangledTypeString { virtual String^ get() override { INativePointer^ instanceSmartPtr = safe_cast(m_Instance); return instanceSmartPtr->MangledTypeString; } } /// ///Get/set the pointer to the native ITK object associated with ///this wrapper instance. /// ///The pointer to the native ITK object. property virtual void* NativePointer { virtual void* get() override { INativePointer^ instanceSmartPtr = safe_cast(m_Instance); return instanceSmartPtr->NativePointer; } virtual void set ( void* value) override { INativePointer^ instanceSmartPtr = safe_cast(m_Instance); instanceSmartPtr->NativePointer = value; } } ///Create an instance of an underlying native itk::Image. ///The pixel type the underlying native itk::Image is templated over. ///The number of dimensions the underlying native itk::Image is templated over. static itkImage^ New ( itkPixelType^ pixelType, unsigned int dim ) { if (pixelType == nullptr) throw gcnew itkInvalidWrappedTypeException("The given pixel type is null. A valid pixel type must be specified to create an instance of a wrapped itk::Image."); itkImage^ newImage = gcnew itkImage(); newImage->m_PixelType = pixelType; newImage->m_Dimension = dim; newImage->CreateInstance(); return newImage; } ///Create an instance of the same underlying native itk::Image type as the given image. ///The type of the underlying native itk::Image to create. static itkImage^ New ( itkImageBase^ image ) { if (image == nullptr) throw gcnew itkInvalidWrappedTypeException("The given image is null. A valid image must be specified to create an instance of a wrapped itk::Image."); itkImage^ newImage = gcnew itkImage(); newImage->m_PixelType = image->PixelType; newImage->m_Dimension = image->Dimension; newImage->CreateInstance(); return newImage; } ///Create an instance of an underlying native itk::Image. ///A string representing the pixel type the underlying native itk::Image is templated over. ///The number of dimensions the underlying native itk::Image is templated over. static itkImage^ New ( String^ mangledPixelType, unsigned int dim ) { if (mangledPixelType == nullptr || mangledPixelType->Length == 0) throw gcnew itkInvalidWrappedTypeException("The given pixel type string is empty. A non-empty, valid pixel type string must be specified to create an instance of a wrapped itk::Image."); itkImage^ newImage = gcnew itkImage(); newImage->m_PixelType = itkPixelType::CreateFromMangledType(mangledPixelType); newImage->m_Dimension = dim; newImage->CreateInstance(); return newImage; } ///Create an instance of an underlying native itk::Image. ///A string representing the pixel type and dimension the underlying native itk::Image is templated over. Eg. "UC2", "F3", etc. static itkImage^ New ( String^ mangledType ) { if (mangledType == nullptr || mangledType->Length == 0) throw gcnew itkInvalidWrappedTypeException("The given image type string is empty. A non-empty, valid image type string must be specified to create an instance of a wrapped itk::Image."); itkImage^ newImage = gcnew itkImage(); newImage->m_PixelType = itkPixelType::CreateFromMangledType(mangledType); newImage->m_Dimension = UInt32::Parse(mangledType->Substring(mangledType->Length-1, 1)); newImage->CreateInstance(); return newImage; } /// ///Remove all observers watching this object. /// /// ///By default, observers are created for all events. Calling this ///method removes all native observers, and therefore prevents ///the firing of managed events. Call AddAnyEventObserver() to ///reset the default observers which enable the managed events. /// virtual void RemoveAllObservers ( ) override { this->m_Instance->RemoveAllObservers(); } /// ///Adds a native observer watching for any event. /// /// ///By default, observers are created for all events. Calling this ///method adds a single native observer for any event. This ///observer invokes the managed events. Therefore, calling this ///method more than once, or calling it without first calling ///RemoveAllObservers(), may cause the managed events to be ///invoked more than once. /// virtual void AddAnyEventObserver ( ) override { this->m_Instance->AddAnyEventObserver( ); this->PassEventsFromTypeToWrapper( ); } ///Read the image from the given file. ///The relative or absolute file path and name. virtual void Read ( System::String^ filename ) override { this->m_Instance->Read(filename); } ///Read an image series from the given filenames. ///An array of absolute file paths. ///This method was added in ManagedITK for simplicity. virtual void ReadSeries ( array^ filenames ) override { this->m_Instance->ReadSeries(filenames); } ///Read an image series from the files matching the given pattern. ///An absolute path to search for the files comprising the series. ///A pattern with wildcard character '*'. ///path="C:/temp/", pattern="test_*.png". ///This method was added in ManagedITK for simplicity. virtual void ReadSeries ( System::String^ path, System::String^ pattern ) override { this->m_Instance->ReadSeries(path, pattern); } /// ///Read an image from the given DICOM directory using GDCM. ///This method uses the first found series identifier. /// ///The directory containing the DICOM series. ///This method was added in ManagedITK for simplicity. virtual void ReadDicomDirectory( System::String^ directory ) override { this->m_Instance->ReadDicomDirectory(directory); } ///Read an image from the given DICOM directory using GDCM. ///The directory containing the DICOM series. ///The identifier of the series to read. ///This method was added in ManagedITK for simplicity. virtual void ReadDicomDirectory( System::String^ directory, System::String^ seriesid ) override { this->m_Instance->ReadDicomDirectory(directory, seriesid); } ///Read an image from the given DICOM directory using GDCM. ///The directory containing the DICOM series. ///The identifier of the series to read. ///Specifies additional DICOM information to distinguish unique volumes within the directory. Eg. "0008|0021" distinguishes series based on date. ///This method was added in ManagedITK for simplicity. virtual void ReadDicomDirectory( System::String^ directory, System::String^ seriesid, ... array^ restrictions) override { this->m_Instance->ReadDicomDirectory(directory, seriesid, restrictions); } ///Write the image to the given file. ///The relative or absolute file path and name. ///This method was added in ManagedITK for simplicity. virtual void Write ( System::String^ filename ) override { this->m_Instance->Write(filename); } ///Write an image series to the files matching the given format. ///The absolute path and filename format for the images. Eg. C:/temp/test_{0}.png. ///A format string for the series numbers. Eg. "000". ///filenameFormat="C:/temp/test_{0}.png" and seriesFormat="000". ///This method was added in ManagedITK for simplicity. virtual void WriteSeries ( System::String^ filenameFormat, System::String^ seriesFormat ) override { this->m_Instance->WriteSeries(filenameFormat, seriesFormat); } /// ///Allocates the memory for an empty image. ///This is the method to use to create an image from scratch (ie. not from IO). ///The regions MUST have been set: call SetRegions() before calling this method. ///The buffer is NOT initialised: call FillBuffer() after calling this method. /// ///This method finalises the creation of the underlying native itk::Image. virtual void Allocate ( ) override { this->m_Instance->Allocate(); } /// ///Convenience method to set the LargestPossibleRegion, BufferedRegion and RequestedRegion. /// ///The image region specifying the largest, requested, and buffered size. /// ///This method does not allocate the image, use Allocate for that purpose. /// virtual void SetRegions ( itkImageRegion^ regions ) override { this->m_Instance->SetRegions(regions); } /// ///Fills the image data with the given value. ///The image regions must be set before calling this method and ///the image must have been allocated. /// ///The pixel value to fill the image. virtual void FillBuffer ( itkPixel^ value ) override { this->m_Instance->FillBuffer(value); } ///Returns the pixel value at the given discrete location. ///The discrete location in image space. ///The pixel value at the given discrete location. virtual itkPixel^ GetPixel ( itkIndex^ index ) override { return m_Instance->GetPixel(index); } ///Set the pixel value at the given discrete location. ///The discrete location in image space. ///The new value to set. virtual void SetPixel ( itkIndex^ index, itkPixel^ value ) override { this->m_Instance->SetPixel(index, value); } ///Separate this image from the pipeline. /// ///This method disconnects the image from the upstream pipeline. ///Hence an Update() from downstream will not propagate back past this image. ///To completely isolate this image from the pipeline, the application must ///remove this image from any filters which it is connected as the input. /// virtual void DisconnectPipeline ( ) override { this->m_Instance->DisconnectPipeline(); } ///Convert a physical point to a continuous index. ///The geometric location in physical space. ///The resultant continuous location in image space. ///true if the resulting index is within the image, false otherwise. virtual bool TransformPhysicalPointToContinuousIndex( itkPoint^ point, [System::Runtime::InteropServices::Out] itkContinuousIndex^% cindex ) override { return this->m_Instance->TransformPhysicalPointToContinuousIndex(point, cindex); } ///Convert a physical point to a discrete index. ///The geometric location in physical space. ///The resultant discrete location in image space. ///true if the resulting index is within the image, false otherwise. virtual bool TransformPhysicalPointToIndex( itkPoint^ point, [System::Runtime::InteropServices::Out] itkIndex^% index ) override { return this->m_Instance->TransformPhysicalPointToIndex(point, index); } ///Convert a continuous index to a physical point. ///The continuous location in image space. ///The resultant geometric location in physical space. virtual void TransformContinuousIndexToPhysicalPoint( itkContinuousIndex^ cindex, [System::Runtime::InteropServices::Out] itkPoint^% point ) override { this->m_Instance->TransformContinuousIndexToPhysicalPoint(cindex, point); } ///Convert a discrete index to a physical point. ///The discrete location in image space. ///The resultant geometric location in physical space. virtual void TransformIndexToPhysicalPoint( itkIndex^ index, [System::Runtime::InteropServices::Out] itkPoint^% point ) override { this->m_Instance->TransformIndexToPhysicalPoint(index, point); } private: ///Creates the correct type instance of the underlying native itk::Image. void CreateInstance ( ) { this->m_IsDisposed = false; String^ nameInstanceType = "itk.itkImage_" + this->PixelType->MangledTypeString + this->Dimension; try { System::Type^ typeInstance = System::Reflection::Assembly::GetExecutingAssembly()->GetType(nameInstanceType); if (typeInstance == nullptr) throw gcnew NullReferenceException("The type '" + nameInstanceType + "' could not be found in " + System::Reflection::Assembly::GetExecutingAssembly()->GetName() ); System::Object^ objInstance = typeInstance->InvokeMember("New", System::Reflection::BindingFlags::InvokeMethod, System::Type::DefaultBinder, nullptr, nullptr); if (objInstance == nullptr) throw gcnew NullReferenceException("Could not invoke the New() method for '" + nameInstanceType + "'."); this->m_Instance = safe_cast(objInstance); this->PassEventsFromTypeToWrapper( ); } catch (Exception^ ex) { throw gcnew itkInvalidWrappedTypeException("Could not create an instance of '" + nameInstanceType + "'. The given type may not be supported or may be invalid.", ex); } } ///Pass managed events from the type instance to this wrapper instance. void PassEventsFromTypeToWrapper() { this->m_Instance->Started += gcnew itkTimedEventHandler(this, &itkImage::Instance_StartedHandler); this->m_Instance->Ended += gcnew itkTimedEventHandler(this, &itkImage::Instance_EndedHandler); this->m_Instance->Aborted += gcnew itkTimedEventHandler(this, &itkImage::Instance_AbortedHandler); this->m_Instance->Iteration += gcnew itkObjectHandler(this, &itkImage::Instance_IterationHandler); this->m_Instance->Modified += gcnew itkObjectHandler(this, &itkImage::Instance_ModifiedHandler); } ///Handle the Started event. void Instance_StartedHandler(itkObject^ sender, System::DateTime time) { this->InvokeStartedEvent(time); } ///Handle the Ended event. void Instance_EndedHandler(itkObject^ sender, System::DateTime time) { this->InvokeEndedEvent(time); } ///Handle the Aborted event. void Instance_AbortedHandler(itkObject^ sender, System::DateTime time) { this->InvokeAbortedEvent(time); } ///Handle the Iteration event. void Instance_IterationHandler(itkObject^ sender) { this->InvokeIterationEvent(); } ///Handle the Modified event. void Instance_ModifiedHandler(itkObject^ sender) { this->InvokeModifiedEvent(); } }; // end ref class } // end namespace itk #endif