From 495aeaf7af1cb34b0a87edf7f8de51440e0c2236 Mon Sep 17 00:00:00 2001 From: delmon Date: Tue, 29 Mar 2011 13:14:10 +0000 Subject: [PATCH] From gdcm 1.x to gdcm 2.0 --- common/clitkDicomRTDoseIO.cxx | 105 +++- common/clitkDicomRTDoseIO.h | 9 + common/clitkImageCommon.cxx | 8 + common/clitkImageCommon.h | 6 +- common/vtkGDCMPolyDataReader.cxx | 809 +++++++++++++++++++++++++++++++ common/vtkGDCMPolyDataReader.h | 84 ++++ 6 files changed, 1009 insertions(+), 12 deletions(-) create mode 100644 common/vtkGDCMPolyDataReader.cxx create mode 100644 common/vtkGDCMPolyDataReader.h diff --git a/common/clitkDicomRTDoseIO.cxx b/common/clitkDicomRTDoseIO.cxx index 6e3eba0..02d953e 100644 --- a/common/clitkDicomRTDoseIO.cxx +++ b/common/clitkDicomRTDoseIO.cxx @@ -21,7 +21,12 @@ #include "clitkCommon.h" // itk include -#include +#if GDCM_MAJOR_VERSION == 2 + #include + #include +#else + #include +#endif #define GFOV_SPACING_TOL (1e-1) @@ -29,67 +34,119 @@ // Read Image Information void clitk::DicomRTDoseIO::ReadImageInformation() { +#if GDCM_MAJOR_VERSION < 2 if(m_GdcmFile) delete m_GdcmFile; m_GdcmFile = new gdcm::File; +#endif - int i, rc; + int i; std::string tmp; float ipp[3]; int dim[3]; float spacing[3]; - float *gfov; /* gfov = GridFrameOffsetVector */ + double *gfov; /* gfov = GridFrameOffsetVector */ int gfov_len; +#if GDCM_MAJOR_VERSION < 2 const char *gfov_str; - + int rc; +#endif + +#if GDCM_MAJOR_VERSION == 2 + m_GdcmImageReader.SetFileName(m_FileName.c_str()); + m_GdcmImageReader.Read(); + gdcm::File* m_GdcmFile = &m_GdcmImageReader.GetFile(); +#else m_GdcmFile->SetMaxSizeLoadEntry (0xffff); m_GdcmFile->SetFileName (m_FileName.c_str()); m_GdcmFile->SetLoadMode (0); m_GdcmFile->Load(); +#endif /* Modality -- better be RTSTRUCT */ +#if GDCM_MAJOR_VERSION == 2 + gdcm::DataSet &ds = m_GdcmFile->GetDataSet(); + + gdcm::Attribute<0x8,0x60> at1; + at1.SetFromDataSet(ds); + tmp = at1.GetValue(); +#else tmp = m_GdcmFile->GetEntryValue (0x0008, 0x0060); +#endif if (strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) { itkExceptionMacro(<< "Error. Input file not RTDOSE: " << m_FileName); } /* ImagePositionPatient */ +#if GDCM_MAJOR_VERSION == 2 + gdcm::Attribute<0x20,0x32> at2; + at2.SetFromDataSet(ds); + ipp[0] = at2.GetValue(0); + ipp[1] = at2.GetValue(1); + ipp[2] = at2.GetValue(2); +#else tmp = m_GdcmFile->GetEntryValue (0x0020, 0x0032); rc = sscanf (tmp.c_str(), "%f\\%f\\%f", &ipp[0], &ipp[1], &ipp[2]); if (rc != 3) { itkExceptionMacro(<< "Error parsing RTDOSE ipp."); } +#endif /* Rows */ +#if GDCM_MAJOR_VERSION == 2 + gdcm::Attribute<0x28,0x10> at3; + at3.SetFromDataSet(ds); + dim[1] = at3.GetValue(); +#else tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0010); rc = sscanf (tmp.c_str(), "%d", &dim[1]); if (rc != 1) { itkExceptionMacro(<< "Error parsing RTDOSE rows."); } +#endif /* Columns */ +#if GDCM_MAJOR_VERSION == 2 + gdcm::Attribute<0x28,0x11> at4; + at4.SetFromDataSet(ds); + dim[0] = at4.GetValue(); +#else tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0011); rc = sscanf (tmp.c_str(), "%d", &dim[0]); if (rc != 1) { itkExceptionMacro(<< "Error parsing RTDOSE columns."); } +#endif /* PixelSpacing */ +#if GDCM_MAJOR_VERSION == 2 + gdcm::Attribute<0x28,0x30> at5; + at5.SetFromDataSet(ds); + spacing[0] = at5.GetValue(0); + spacing[1] = at5.GetValue(1); +#else tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0030); rc = sscanf (tmp.c_str(), "%g\\%g", &spacing[0], &spacing[1]); - if (rc != 2) { itkExceptionMacro(<< "Error parsing RTDOSE pixel spacing."); } +#endif /* GridFrameOffsetVector */ +#if GDCM_MAJOR_VERSION == 2 + gdcm::Attribute<0x3004,0x000C> at6; + const gdcm::DataElement& de6 = ds.GetDataElement( at6.GetTag() ); + at6.SetFromDataElement(de6); + gfov = (double*) at6.GetValues(); + gfov_len = at6.GetNumberOfValues(); +#else tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000C); gfov = 0; gfov_len = 0; gfov_str = tmp.c_str(); while (1) { int len; - gfov = (float*) realloc (gfov, (gfov_len + 1) * sizeof(float)); + gfov = (double*) realloc (gfov, (gfov_len + 1) * sizeof(double)); rc = sscanf (gfov_str, "%g%n", &gfov[gfov_len], &len); if (rc != 1) { break; @@ -100,6 +157,8 @@ void clitk::DicomRTDoseIO::ReadImageInformation() gfov_str ++; } } +#endif + dim[2] = gfov_len; if (gfov_len == 0) { itkExceptionMacro(<< "Error parsing RTDOSE gfov."); @@ -122,7 +181,7 @@ void clitk::DicomRTDoseIO::ReadImageInformation() if (i == 1) { spacing[2] = gfov[1] - gfov[0]; } else { - float sp = gfov[i] - gfov[i-1]; + double sp = gfov[i] - gfov[i-1]; if (fabs(sp - spacing[2]) > GFOV_SPACING_TOL) { itkExceptionMacro(<< "Error RTDOSE grid has irregular spacing:" << sp << " vs " << spacing[2]); @@ -130,12 +189,20 @@ void clitk::DicomRTDoseIO::ReadImageInformation() } } +#if GDCM_MAJOR_VERSION < 2 free (gfov); +#endif /* DoseGridScaling */ +#if GDCM_MAJOR_VERSION == 2 + gdcm::Attribute<0x3004,0x000E> at7 = { 1. } ; + at7.SetFromDataSet(ds); + m_DoseScaling = at7.GetValue(); +#else m_DoseScaling = 1.0; tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000E); rc = sscanf (tmp.c_str(), "%f", &m_DoseScaling); +#endif /* If element doesn't exist, scaling is 1.0 */ // set dimension values @@ -157,6 +224,17 @@ void clitk::DicomRTDoseIO::ReadImageInformation() // Read Image Information bool clitk::DicomRTDoseIO::CanReadFile(const char* FileNameToRead) { +#if GDCM_MAJOR_VERSION == 2 + gdcm::Reader creader; + creader.SetFileName(FileNameToRead); + if (!creader.Read()) + return false; + + gdcm::DataSet &ds = creader.GetFile().GetDataSet(); + gdcm::Attribute<0x8,0x60> at1; + at1.SetFromDataSet(ds); + std::string tmp = at1.GetValue(); +#else // opening dicom input file gdcm::File dcmFile; dcmFile.SetFileName(FileNameToRead); @@ -170,6 +248,7 @@ bool clitk::DicomRTDoseIO::CanReadFile(const char* FileNameToRead) /* Modality -- better be RTDOSE */ std::string tmp = dcmFile.GetEntryValue (0x0008, 0x0060); +#endif if (!strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) { return true; } @@ -191,13 +270,17 @@ clitk::DicomRTDoseIO::dose_copy_raw (float *img_out, T *img_in, int nvox, float // Read Image Content void clitk::DicomRTDoseIO::Read(void * buffer) { - float *img = (float*) buffer; - unsigned long npix = 1; for(unsigned int i=0; inpix; i++) { //img[i] = image_data[i] * m_DoseScaling; // } - - delete m_GdcmFile; } //-------------------------------------------------------------------- diff --git a/common/clitkDicomRTDoseIO.h b/common/clitkDicomRTDoseIO.h index b5679aa..dc09455 100644 --- a/common/clitkDicomRTDoseIO.h +++ b/common/clitkDicomRTDoseIO.h @@ -24,6 +24,9 @@ // itk include #include #include +#if GDCM_MAJOR_VERSION == 2 + #include +#endif // std include #include @@ -44,7 +47,9 @@ public: DicomRTDoseIO():Superclass() { mustWriteHeader = false; +#if GDCM_MAJOR_VERSION < 2 m_GdcmFile=NULL; +#endif } /** Method for creation through the object factory. */ @@ -72,7 +77,11 @@ protected: bool mustWriteHeader; int m_HeaderSize; std::ofstream file; +#if GDCM_MAJOR_VERSION == 2 + gdcm::ImageReader m_GdcmImageReader; +#else gdcm::File *m_GdcmFile; +#endif float m_DoseScaling; }; // end class DicomRTDoseIO diff --git a/common/clitkImageCommon.cxx b/common/clitkImageCommon.cxx index cfcbbe3..f5a8d3c 100644 --- a/common/clitkImageCommon.cxx +++ b/common/clitkImageCommon.cxx @@ -63,6 +63,13 @@ void clitk::ReadImageDimensionAndPixelType(const std::string & filename, gdcm::File * clitk::readDicomHeader(const std::string & filename, const bool verbose) { +#if GDCM_MAJOR_VERSION == 2 + gdcm::Reader hreader; + hreader.SetFileName(filename.c_str()); + hreader.Read(); + gdcm::SmartPointer p = hreader.GetFile(); + return p; +#else if (verbose) { std::cout << "Reading DICOM <" << filename << ">" << std::endl; } @@ -71,6 +78,7 @@ gdcm::File * clitk::readDicomHeader(const std::string & filename, header->SetMaxSizeLoadEntry(16384); // required ? header->Load(); return header; +#endif } ///-------------------------------------------------------------------- diff --git a/common/clitkImageCommon.h b/common/clitkImageCommon.h index 9e61223..38800c4 100644 --- a/common/clitkImageCommon.h +++ b/common/clitkImageCommon.h @@ -27,7 +27,11 @@ #include "itkImageSeriesReader.h" #include "itkImageFileWriter.h" #include "gdcmFile.h" -#include "gdcmFileHelper.h" +#if GDCM_MAJOR_VERSION == 2 + #include "gdcmReader.h" +#else + #include "gdcmFileHelper.h" +#endif namespace clitk { diff --git a/common/vtkGDCMPolyDataReader.cxx b/common/vtkGDCMPolyDataReader.cxx new file mode 100644 index 0000000..b7062ec --- /dev/null +++ b/common/vtkGDCMPolyDataReader.cxx @@ -0,0 +1,809 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGDCMPolyDataReader.h" + +#include "vtkObjectFactory.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkDoubleArray.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkMedicalImageProperties.h" +#include "vtkRTStructSetProperties.h" + +#include "gdcmReader.h" +#include "gdcmSmartPointer.h" +#include "gdcmAttribute.h" +#include "gdcmSequenceOfItems.h" + +vtkCxxRevisionMacro(vtkGDCMPolyDataReader, "$Revision: 1.1 $") +vtkStandardNewMacro(vtkGDCMPolyDataReader) + +//---------------------------------------------------------------------------- +vtkGDCMPolyDataReader::vtkGDCMPolyDataReader() +{ + this->FileName = NULL; + this->SetNumberOfInputPorts(0); + this->MedicalImageProperties = vtkMedicalImageProperties::New(); + this->RTStructSetProperties = vtkRTStructSetProperties::New(); +} + +//---------------------------------------------------------------------------- +vtkGDCMPolyDataReader::~vtkGDCMPolyDataReader() +{ + this->SetFileName(0); + this->MedicalImageProperties->Delete(); + this->RTStructSetProperties->Delete(); +} + +//---------------------------------------------------------------------------- +// inline keyword is needed since GetStringValueFromTag was copy/paste from vtkGDCMImageReader +// FIXME: need to restructure code to avoid copy/paste +inline const char *GetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds) +{ + static std::string buffer; + buffer = ""; // cleanup previous call + + if( ds.FindDataElement( t ) ) + { + const gdcm::DataElement& de = ds.GetDataElement( t ); + const gdcm::ByteValue *bv = de.GetByteValue(); + if( bv ) // Can be Type 2 + { + buffer = std::string( bv->GetPointer(), bv->GetLength() ); + // Will be padded with at least one \0 + } + } + + // Since return is a const char* the very first \0 will be considered + return buffer.c_str(); +} + +//---------------------------------------------------------------------------- +void vtkGDCMPolyDataReader::FillMedicalImageInformation(const gdcm::Reader &reader) +{ + const gdcm::File &file = reader.GetFile(); + const gdcm::DataSet &ds = file.GetDataSet(); + + this->RTStructSetProperties->SetStructureSetLabel( GetStringValueFromTag( gdcm::Tag(0x3006,0x0002), ds) ); + this->RTStructSetProperties->SetStructureSetName( GetStringValueFromTag( gdcm::Tag(0x3006,0x0004), ds) ); + this->RTStructSetProperties->SetStructureSetDate( GetStringValueFromTag( gdcm::Tag(0x3006,0x0008), ds) ); + this->RTStructSetProperties->SetStructureSetTime( GetStringValueFromTag( gdcm::Tag(0x3006,0x0009), ds) ); + this->RTStructSetProperties->SetSOPInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0008,0x0018), ds) ); + this->RTStructSetProperties->SetStudyInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000d), ds) ); + this->RTStructSetProperties->SetSeriesInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000e), ds) ); + + // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h + // For ex: DICOM (0010,0010) = DOE,JOHN + this->MedicalImageProperties->SetPatientName( GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds) ); + // For ex: DICOM (0010,0020) = 1933197 + this->MedicalImageProperties->SetPatientID( GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds) ); + // For ex: DICOM (0010,1010) = 031Y + this->MedicalImageProperties->SetPatientAge( GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds) ); + // For ex: DICOM (0010,0040) = M + this->MedicalImageProperties->SetPatientSex( GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) ); + // For ex: DICOM (0010,0030) = 19680427 + this->MedicalImageProperties->SetPatientBirthDate( GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) ); +#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) + // For ex: DICOM (0008,0020) = 20030617 + this->MedicalImageProperties->SetStudyDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds) ); +#endif + // For ex: DICOM (0008,0022) = 20030617 + this->MedicalImageProperties->SetAcquisitionDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds) ); +#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) + // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 + this->MedicalImageProperties->SetStudyTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds) ); +#endif + // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 + this->MedicalImageProperties->SetAcquisitionTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds) ); + // For ex: DICOM (0008,0023) = 20030617 + this->MedicalImageProperties->SetImageDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds) ); + // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 + this->MedicalImageProperties->SetImageTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds) ); + // For ex: DICOM (0020,0013) = 1 + this->MedicalImageProperties->SetImageNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds) ); + // For ex: DICOM (0020,0011) = 902 + this->MedicalImageProperties->SetSeriesNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) ); + // For ex: DICOM (0008,103e) = SCOUT + this->MedicalImageProperties->SetSeriesDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) ); + // For ex: DICOM (0020,0010) = 37481 + this->MedicalImageProperties->SetStudyID( GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) ); + // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL + this->MedicalImageProperties->SetStudyDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) ); + // For ex: DICOM (0008,0060)= CT + this->MedicalImageProperties->SetModality( GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) ); + // For ex: DICOM (0008,0070) = Siemens + this->MedicalImageProperties->SetManufacturer( GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds) ); + // For ex: DICOM (0008,1090) = LightSpeed QX/i + this->MedicalImageProperties->SetManufacturerModelName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds) ); + // For ex: DICOM (0008,1010) = LSPD_OC8 + this->MedicalImageProperties->SetStationName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds) ); + // For ex: DICOM (0008,0080) = FooCity Medical Center + this->MedicalImageProperties->SetInstitutionName( GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds) ); + // For ex: DICOM (0018,1210) = Bone + this->MedicalImageProperties->SetConvolutionKernel( GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds) ); + // For ex: DICOM (0018,0050) = 0.273438 + this->MedicalImageProperties->SetSliceThickness( GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds) ); + // For ex: DICOM (0018,0060) = 120 + this->MedicalImageProperties->SetKVP( GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds) ); + // For ex: DICOM (0018,1120) = 15 + this->MedicalImageProperties->SetGantryTilt( GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds) ); + // For ex: DICOM (0018,0081) = 105 + this->MedicalImageProperties->SetEchoTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds) ); + // For ex: DICOM (0018,0091) = 35 + this->MedicalImageProperties->SetEchoTrainLength( GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds) ); + // For ex: DICOM (0018,0080) = 2040 + this->MedicalImageProperties->SetRepetitionTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds) ); + // For ex: DICOM (0018,1150) = 5 + this->MedicalImageProperties->SetExposureTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds) ); + // For ex: DICOM (0018,1151) = 400 + this->MedicalImageProperties->SetXRayTubeCurrent( GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds) ); + // For ex: DICOM (0018,1152) = 114 + this->MedicalImageProperties->SetExposure( GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds) ); + + // virtual void AddWindowLevelPreset(double w, double l); + // (0028,1050) DS [ 498\ 498] # 12, 2 WindowCenter + // (0028,1051) DS [ 1063\ 1063] # 12, 2 WindowWidth + gdcm::Tag twindowcenter(0x0028,0x1050); + gdcm::Tag twindowwidth(0x0028,0x1051); + if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) ) + { + const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter ); + const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth ); + const gdcm::ByteValue *bvwc = windowcenter.GetByteValue(); + const gdcm::ByteValue *bvww = windowwidth.GetByteValue(); + if( bvwc && bvww ) // Can be Type 2 + { + //gdcm::Attributes<0x0028,0x1050> at; + gdcm::Element elwc; + std::stringstream ss1; + std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() ); + ss1.str( swc ); + gdcm::VR vr = gdcm::VR::DS; + unsigned int vrsize = vr.GetSizeof(); + unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), swc.size()); + elwc.SetLength( count * vrsize ); + elwc.Read( ss1 ); + std::stringstream ss2; + std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() ); + ss2.str( sww ); + gdcm::Element elww; + elww.SetLength( count * vrsize ); + elww.Read( ss2 ); + //assert( elww.GetLength() == elwc.GetLength() ); + for(unsigned int i = 0; i < elwc.GetLength(); ++i) + { + this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) ); + } + } + } + gdcm::Tag twindowexplanation(0x0028,0x1055); + if( ds.FindDataElement( twindowexplanation ) ) + { + const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation ); + const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue(); + if( bvwe ) // Can be Type 2 + { + int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets(); + gdcm::Element elwe; // window explanation + gdcm::VR vr = gdcm::VR::LO; + std::stringstream ss; + ss.str( "" ); + std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() ); + unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), swe.size()); (void)count; + // I found a case with only one W/L but two comments: WINDOW1\WINDOW2 + // SIEMENS-IncompletePixelData.dcm + //assert( count >= (unsigned int)n ); + elwe.SetLength( /*count*/ n * vr.GetSizeof() ); + ss.str( swe ); + elwe.Read( ss ); + for(int i = 0; i < n; ++i) + { + this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() ); + } + } + } + +#if 0 + // gdcmData/JDDICOM_Sample4.dcm + // -> (0008,0060) CS [DM Digital microscopy] # 24, 1 Modality + gdcm::MediaStorage ms1 = gdcm::MediaStorage::SecondaryCaptureImageStorage; + ms1.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality ); + gdcm::MediaStorage ms2; + ms2.SetFromFile( reader.GetFile() ); + if( ms2 != ms1 && ms2 != gdcm::MediaStorage::SecondaryCaptureImageStorage ) + { + vtkWarningMacro( "SHOULD NOT HAPPEN. Unrecognized Modality: " << this->MedicalImageProperties->GetModality() + << " Will be set instead to the known one: " << ms2.GetModality() ) + this->MedicalImageProperties->SetModality( ms2.GetModality() ); + } +#endif + + // Add more info: + +} + +//(3006,0022) ?? (IS) [2 ] # 2,1 ROI Number +//(3006,0024) ?? (UI) [2.16.840.1.114362.1.759508.1251415878280.193] # 44,1 Referenced Frame of Reference UID +//(3006,0026) ?? (LO) [Bladder ] # 8,1 ROI Name +//(3006,0036) ?? (CS) [MANUAL] # 6,1 ROI Generation Algorithm + +int vtkGDCMPolyDataReader::RequestData_RTStructureSetStorage(gdcm::Reader const &reader, + vtkInformationVector *outputVector) +{ +// This is done in RequestInformation +// gdcm::MediaStorage ms; +// ms.SetFromFile( reader.GetFile() ); +// //std::cout << ms << std::endl; +// if( ms != gdcm::MediaStorage::RTStructureSetStorage ) +// { +// return 0; +// } + + const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); + // (3006,0010) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedFrameOfReferenceSequence + // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence + // (3006,0039) SQ (Sequence with explicit length #=4) # 24216, 1 ROIContourSequence + gdcm::Tag troicsq(0x3006,0x0039); + if( !ds.FindDataElement( troicsq ) ) + { + return 0; + } + gdcm::Tag tssroisq(0x3006,0x0020); + if( !ds.FindDataElement( tssroisq ) ) + { + return 0; + } + gdcm::Tag trefframerefsq(0x3006,0x0010); + if( !ds.FindDataElement( trefframerefsq ) ) + { + return 0; + } + const gdcm::DataElement &refframerefsq = ds.GetDataElement( trefframerefsq ); + gdcm::SmartPointer sqi0 = refframerefsq.GetValueAsSQ(); + if( !sqi0 || !sqi0->GetNumberOfItems() ) + { + return 0; + } + assert( sqi0->GetNumberOfItems() == 1 ); + for(unsigned int pd = 0; pd < sqi0->GetNumberOfItems(); ++pd) + { + const gdcm::Item & item = sqi0->GetItem(pd+1); // Item start at #1 + const gdcm::DataSet& nestedds = item.GetNestedDataSet(); + // (3006,0012) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedStudySequence + gdcm::Attribute<0x0020,0x052> frameofreferenceuid; + frameofreferenceuid.SetFromDataSet( nestedds ); + this->RTStructSetProperties->SetReferenceFrameOfReferenceUID( + frameofreferenceuid.GetValue() ); + gdcm::Tag trtrefstudysq(0x3006,0x0012); + if( !nestedds.FindDataElement( trtrefstudysq) ) + { + return 0; + } + const gdcm::DataElement &rtrefstudysq = nestedds.GetDataElement( trtrefstudysq ); + gdcm::SmartPointer sqi00 = rtrefstudysq.GetValueAsSQ(); + if( !sqi00 || !sqi00->GetNumberOfItems() ) + { + return 0; + } + assert( sqi00->GetNumberOfItems() == 1 ); + for(unsigned int pd0 = 0; pd0 < sqi00->GetNumberOfItems(); ++pd0) + { + const gdcm::Item & item = sqi00->GetItem(pd0+1); // Item start at #1 + const gdcm::DataSet& nestedds = item.GetNestedDataSet(); + + // (3006,0014) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedSeriesSequence + gdcm::Tag trtrefseriessq(0x3006,0x0014); + if( !nestedds.FindDataElement( trtrefseriessq) ) + { + return 0; + } + const gdcm::DataElement &rtrefseriessq = nestedds.GetDataElement( trtrefseriessq); + + gdcm::SmartPointer sqi000 = rtrefseriessq.GetValueAsSQ(); + if( !sqi000 || !sqi000->GetNumberOfItems() ) + { + return 0; + } + assert( sqi000->GetNumberOfItems() == 1 ); + for(unsigned int pd00 = 0; pd00 < sqi000->GetNumberOfItems(); ++pd00) + { + const gdcm::Item & item = sqi000->GetItem(pd00+1); // Item start at #1 + const gdcm::DataSet& nestedds = item.GetNestedDataSet(); + + gdcm::Attribute<0x0020,0x000e> seriesinstanceuid; + seriesinstanceuid.SetFromDataSet( nestedds ); + this->RTStructSetProperties->SetReferenceSeriesInstanceUID( + seriesinstanceuid.GetValue() ); + + + // (3006,0016) SQ (Sequence with undefined length #=162) # u/l, 1 ContourImageSequence + gdcm::Tag tcontourimageseq(0x3006,0x0016); + if( !nestedds.FindDataElement( tcontourimageseq) ) + { + return 0; + } + const gdcm::DataElement &contourimageseq = nestedds.GetDataElement( tcontourimageseq ); + gdcm::SmartPointer sqi0000 = contourimageseq.GetValueAsSQ(); + if( !sqi0000 || !sqi0000->GetNumberOfItems() ) + { + return 0; + } + + assert( sqi0000->GetNumberOfItems() != 1 ); + for(unsigned int pd000 = 0; pd000 < sqi0000->GetNumberOfItems(); ++pd000) + { + const gdcm::Item & item = sqi0000->GetItem(pd000+1); // Item start at #1 + const gdcm::DataSet& nestedds = item.GetNestedDataSet(); + gdcm::Attribute<0x0008,0x1150> refsopclassuid; + refsopclassuid.SetFromDataSet( nestedds ); + gdcm::Attribute<0x0008,0x1155> refinstanceuid; + refinstanceuid.SetFromDataSet( nestedds ); + this->RTStructSetProperties->AddReferencedFrameOfReference( refsopclassuid.GetValue().c_str(), +refinstanceuid.GetValue().c_str() ); + } + + } + + } + } + + const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq ); + //std::cout << roicsq << std::endl; + //const gdcm::SequenceOfItems *sqi_debug = roicsq.GetSequenceOfItems(); + gdcm::SmartPointer sqi = roicsq.GetValueAsSQ(); + if( !sqi || !sqi->GetNumberOfItems() ) + { + return 0; + } + const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq ); + //const gdcm::SequenceOfItems *ssqi = ssroisq.GetSequenceOfItems(); + gdcm::SmartPointer ssqi = ssroisq.GetValueAsSQ(); + if( !ssqi || !ssqi->GetNumberOfItems() ) + { + return 0; + } + + // For each Item in the DataSet create a vtkPolyData + for(unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd) + { + //StructureSetROI structuresetroi; + // get the info object + vtkInformation *outInfo1 = outputVector->GetInformationObject(pd); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo1->Get(vtkDataObject::DATA_OBJECT())); + + + const gdcm::Item & item = sqi->GetItem(pd+1); // Item start at #1 + //std::cout << item << std::endl; + const gdcm::Item & sitem = ssqi->GetItem(pd+1); // Item start at #1 + const gdcm::DataSet& snestedds = sitem.GetNestedDataSet(); + // (3006,0026) ?? (LO) [date] # 4,1 ROI Name + gdcm::Tag stcsq(0x3006,0x0026); + if( !snestedds.FindDataElement( stcsq ) ) + { + continue; + } + const gdcm::DataElement &sde = snestedds.GetDataElement( stcsq ); + std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength()); + //structuresetroi.ROIName = s; + gdcm::Attribute<0x3006,0x0022> roinumber; + roinumber.SetFromDataSet( snestedds ); + //structuresetroi.ROINumber = roinumber.GetValue(); + gdcm::Attribute<0x3006,0x0024> refframeuid; + refframeuid.SetFromDataSet( snestedds ); + //structuresetroi.RefFrameRefUID = refframeuid.GetValue(); + gdcm::Attribute<0x3006,0x0026> roiname; + roiname.SetFromDataSet( snestedds ); + assert( s == roiname.GetValue() ); + gdcm::Attribute<0x3006,0x0036> roigenalg; + roigenalg.SetFromDataSet( snestedds ); + //structuresetroi.ROIGenerationAlgorithm = roigenalg.GetValue(); + //structuresetrois.push_back( structuresetroi ); + + this->RTStructSetProperties->AddStructureSetROI( + roinumber.GetValue(), + refframeuid.GetValue(), + roiname.GetValue(), + roigenalg.GetValue() + ); + + const gdcm::DataSet& nestedds = item.GetNestedDataSet(); + //std::cout << nestedds << std::endl; + //(3006,002a) IS [255\192\96] # 10,3 ROI Display Color + gdcm::Tag troidc(0x3006,0x002a); + gdcm::Attribute<0x3006,0x002a> color = {}; + if( nestedds.FindDataElement( troidc) ) + { + const gdcm::DataElement &decolor = nestedds.GetDataElement( troidc ); + color.SetFromDataElement( decolor ); + //std::cout << "color:" << color[0] << "," << color[1] << "," << color[2] << std::endl; + } + //(3006,0040) SQ (Sequence with explicit length #=8) # 4326, 1 ContourSequence + gdcm::Tag tcsq(0x3006,0x0040); + if( !nestedds.FindDataElement( tcsq ) ) + { + continue; + } + const gdcm::DataElement& csq = nestedds.GetDataElement( tcsq ); + //std::cout << csq << std::endl; + + //const gdcm::SequenceOfItems *sqi2 = csq.GetSequenceOfItems(); + gdcm::SmartPointer sqi2 = csq.GetValueAsSQ(); + if( !sqi2 || !sqi2->GetNumberOfItems() ) + { + continue; + } + unsigned int nitems = sqi2->GetNumberOfItems(); + //std::cout << nitems << std::endl; + //this->SetNumberOfOutputPorts(nitems); + vtkDoubleArray *scalars = vtkDoubleArray::New(); + scalars->SetNumberOfComponents(3); + + vtkPoints *newPts = vtkPoints::New(); + //std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength()); + //std::cout << s << std::endl; + //newPts->GetData()->SetName( s.c_str() ); + // In VTK there is no API to specify the name of a vtkPolyData, you can only specify Name + // for the scalars (pointdata or celldata), so let's do that... + //scalars->SetName( structuresetroi.ROIName.c_str() ); + scalars->SetName( roiname.GetValue().c_str() ); + vtkCellArray *polys = vtkCellArray::New(); + for(unsigned int i = 0; i < nitems; ++i) + { + const gdcm::Item & item2 = sqi2->GetItem(i+1); // Item start at #1 + + const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet(); + //std::cout << nestedds2 << std::endl; + // (3006,0050) DS [43.57636\65.52504\-10.0\46.043102\62.564945\-10.0\49.126537\60.714... # 398,48 ContourData + gdcm::Tag tcontourdata(0x3006,0x0050); + const gdcm::DataElement & contourdata = nestedds2.GetDataElement( tcontourdata ); + //std::cout << contourdata << std::endl; + + //const gdcm::ByteValue *bv = contourdata.GetByteValue(); + gdcm::Attribute<0x3006,0x0042> contgeotype; + contgeotype.SetFromDataSet( nestedds2 ); + assert( contgeotype.GetValue() == "CLOSED_PLANAR " ); + + gdcm::Attribute<0x3006,0x0046> numcontpoints; + numcontpoints.SetFromDataSet( nestedds2 ); + + gdcm::Attribute<0x3006,0x0050> at; + at.SetFromDataElement( contourdata ); + + { + assert( nestedds2.FindDataElement( gdcm::Tag(0x3006,0x0016) ) ); + const gdcm::DataElement &contourimagesequence = nestedds2.GetDataElement( gdcm::Tag(0x3006,0x0016) ); + gdcm::SmartPointer contourimagesequence_sqi = contourimagesequence.GetValueAsSQ(); + assert( contourimagesequence_sqi && contourimagesequence_sqi->GetNumberOfItems() == 1 ); + const gdcm::Item & theitem = contourimagesequence_sqi->GetItem(1); + const gdcm::DataSet& nestedds = theitem.GetNestedDataSet(); + + gdcm::Attribute<0x0008,0x1150> classat; + classat.SetFromDataSet( nestedds ); + gdcm::Attribute<0x0008,0x1155> instat; + instat.SetFromDataSet( nestedds ); + + this->RTStructSetProperties->AddContourReferencedFrameOfReference( pd, + classat.GetValue(), instat.GetValue() ); + } + + //newPts->SetNumberOfPoints( at.GetNumberOfValues() / 3 ); + //assert( at.GetNumberOfValues() % 3 == 0); // FIXME + const double* pts = at.GetValues(); + vtkIdType buffer[256]; + vtkIdType *ptIds; + unsigned int npts = at.GetNumberOfValues() / 3; + assert( npts == numcontpoints.GetValue() ); + if(npts>256) + { + ptIds = new vtkIdType[npts]; + } + else + { + ptIds = buffer; + } + for(unsigned int i = 0; i < npts * 3; i+=3) + { + float x[3]; + x[0] = pts[i+0]; + x[1] = pts[i+1]; + x[2] = pts[i+2]; + vtkIdType ptId = newPts->InsertNextPoint( x ); + ptIds[i / 3] = ptId; + } + // Each Contour Data is in fact a Cell: + vtkIdType cellId = polys->InsertNextCell( npts , ptIds); + scalars->InsertTuple3(cellId, (double)color[0]/255.0, (double)color[1]/255.0, (double)color[2]/255.0); + if(npts>256) + { + delete[] ptIds; + } + } + output->SetPoints(newPts); + newPts->Delete(); + output->SetPolys(polys); + polys->Delete(); + output->GetCellData()->SetScalars(scalars); + scalars->Delete(); + } + + // Add the Observations: + // we can only be doing it here once all RT are loaded, since we will + // attach observation to *existing* rtstruct + gdcm::Tag trtroiobssq(0x3006,0x0080); + if( !ds.FindDataElement( trtroiobssq ) ) + { + return 0; + } + const gdcm::DataElement &rtroiobssq = ds.GetDataElement( trtroiobssq ); + gdcm::SmartPointer rtroiobssqsqi = rtroiobssq.GetValueAsSQ(); + if( !rtroiobssqsqi || !rtroiobssqsqi->GetNumberOfItems() ) + { + return 0; + } + for(unsigned int obs = 0; obs < rtroiobssqsqi->GetNumberOfItems(); ++obs) + { + const gdcm::Item & item = rtroiobssqsqi->GetItem(obs+1); // Item start at #1 + const gdcm::DataSet& nestedds = item.GetNestedDataSet(); + gdcm::Attribute<0x3006,0x0082> observationnumber; + observationnumber.SetFromDataSet( nestedds ); + gdcm::Attribute<0x3006,0x0084> referencedroinumber; + referencedroinumber.SetFromDataSet( nestedds ); + gdcm::Attribute<0x3006,0x00a4> rtroiinterpretedtype; + rtroiinterpretedtype.SetFromDataSet( nestedds ); + gdcm::Attribute<0x3006,0x00a6> roiinterpreter; + roiinterpreter.SetFromDataSet( nestedds ); + this->RTStructSetProperties-> + AddStructureSetROIObservation( referencedroinumber.GetValue(), + observationnumber.GetValue(), + rtroiinterpretedtype.GetValue(), + roiinterpreter.GetValue() ); + } + + return 1; +} + +int vtkGDCMPolyDataReader::RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader, + vtkInformationVector *outputVector) +{ + const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); + // (5400,0100) SQ (Sequence with undefined length #=1) # u/l, 1 WaveformSequence + gdcm::Tag twsq(0x5400,0x0100); + if( !ds.FindDataElement( twsq) ) + { + return 0; + } + const gdcm::DataElement &wsq = ds.GetDataElement( twsq ); + //std::cout << wsq << std::endl; + //const gdcm::SequenceOfItems *sqi = wsq.GetSequenceOfItems(); + gdcm::SmartPointer sqi = wsq.GetValueAsSQ(); + if( !sqi || !sqi->GetNumberOfItems() ) + { + return 0; + } + + const gdcm::Item & item = sqi->GetItem(1); // Item start at #1 + const gdcm::DataSet& nestedds = item.GetNestedDataSet(); + + // (5400,1004) US 16 # 2, 1 WaveformBitsAllocated + gdcm::Tag twba(0x5400,0x1004); + if( !nestedds.FindDataElement( twba ) ) + { + return 0; + } + const gdcm::DataElement &wba= nestedds.GetDataElement( twba ); + + //std::cout << wba << std::endl; + // (5400,1006) CS [SS] # 2, 1 WaveformSampleInterpretation + // (5400,1010) OW 00ba\0030\ff76\ff8b\00a2\ffd3\ffae\ff50\0062\00c4\011e\00c2\00ba... # 57600, 1 WaveformData + gdcm::Tag twd(0x5400,0x1010); + if( !nestedds.FindDataElement( twd ) ) + { + return 0; + } + const gdcm::DataElement &wd = nestedds.GetDataElement( twd ); + const gdcm::ByteValue *bv = wd.GetByteValue(); + size_t len = bv->GetLength(); + int16_t *p = (int16_t*)bv; + + // get the info object + int pd = 0; + vtkInformation *outInfo1 = outputVector->GetInformationObject(pd); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo1->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *newPts = vtkPoints::New(); + size_t npts = len / 2; + //npts = 10; // DEBUG ! + for(size_t i = 0; i < npts; ++i ) + { + float x[3]; + x[0] = (float)p[i] / 8800; + //std::cout << p[i] << std::endl; + x[1] = i; + x[2] = 0; + vtkIdType ptId = newPts->InsertNextPoint( x ); + } + output->SetPoints(newPts); + newPts->Delete(); + + vtkCellArray* lines = vtkCellArray::New(); + for ( int i = 0; i < newPts->GetNumberOfPoints() - 1; ++i ) + { + vtkIdType topol[2]; + topol[0] = i; + topol[1] = i+1; + lines->InsertNextCell( 2, topol ); + } + + output->SetLines(lines); + lines->Delete(); + output->BuildCells(); + //output->GetCellData()->SetScalars(scalars); + //scalars->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGDCMPolyDataReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + //vtkPoints *newPts, *mergedPts; + //vtkCellArray *newPolys, *mergedPolys; + //vtkFloatArray *newScalars=0, *mergedScalars=0; + + // All of the data in the first piece. + if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) + { + return 0; + } + + if ( !this->FileName || !*this->FileName ) + { + vtkErrorMacro(<<"A FileName must be specified."); + return 0; + } + + gdcm::Reader reader; + reader.SetFileName( this->FileName ); + if( !reader.Read() ) + { + return 0; + } + + gdcm::MediaStorage ms; + ms.SetFromFile( reader.GetFile() ); + + int ret; + if( ms == gdcm::MediaStorage::RTStructureSetStorage ) + { + ret = this->RequestData_RTStructureSetStorage(reader, outputVector); + } + else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage) + { + ret = this->RequestData_HemodynamicWaveformStorage(reader, outputVector); + } + else + { + // not handled assume error + ret = 0; + } + + return ret; +} + +int vtkGDCMPolyDataReader::RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader) +{ + const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); + // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence + gdcm::Tag tssroisq(0x3006,0x0020); + if( !ds.FindDataElement( tssroisq ) ) + { + return 0; + } + + const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq ); + //const gdcm::SequenceOfItems *sqi = ssroisq.GetSequenceOfItems(); + gdcm::SmartPointer sqi = ssroisq.GetValueAsSQ(); + if( !sqi || !sqi->GetNumberOfItems() ) + { + return 0; + } + unsigned int npds = sqi->GetNumberOfItems(); + + //std::cout << "Nb pd:" << npds << std::endl; + this->SetNumberOfOutputPorts( npds ); + + // Allocate + for(unsigned int i = 1; i < npds; ++i) // first output is allocated for us + { + vtkPolyData *output2 = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(i, output2); + output2->Delete(); + } + return 1; +} + +int vtkGDCMPolyDataReader::RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & reader) +{ + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGDCMPolyDataReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object +// vtkInformation *outInfo = outputVector->GetInformationObject(0); +// +// outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), +// -1); + gdcm::Reader reader; + reader.SetFileName( this->FileName ); + if( !reader.Read() ) + { + return 0; + } + + gdcm::MediaStorage ms; + ms.SetFromFile( reader.GetFile() ); + + int ret; + if( ms == gdcm::MediaStorage::RTStructureSetStorage ) + { + ret = this->RequestInformation_RTStructureSetStorage(reader); + } + else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage) + { + ret = this->RequestInformation_HemodynamicWaveformStorage(reader); + } + else + { + // not handled assume error + ret = 0; + } + + if( ret ) + { + // Ok let's fill in the 'extra' info: + this->FillMedicalImageInformation(reader); + } + + return ret; +} + + +//---------------------------------------------------------------------------- +void vtkGDCMPolyDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + +} diff --git a/common/vtkGDCMPolyDataReader.h b/common/vtkGDCMPolyDataReader.h new file mode 100644 index 0000000..6fe90bd --- /dev/null +++ b/common/vtkGDCMPolyDataReader.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGDCMPolyDataReader - read DICOM PolyData files (Contour Data...) +// .SECTION Description +// For now only support RTSTRUCT (RT Structure Set Storage) +// .SECTION TODO +// Need to do the same job for DVH Sequence/DVH Data... +// .SECTION Warning +// When using vtkGDCMPolyDataReader in conjonction with vtkGDCMImageReader +// it is *required* that FileLowerLeft is set to ON as coordinate system +// would be inconsistant in between the two data structures. +// +// .SECTION See Also +// vtkGDCMImageReader vtkGDCMPolyDataWriter vtkRTStructSetProperties + + +#ifndef VTKGDCMPOLYDATAREADER_H +#define VTKGDCMPOLYDATAREADER_H + +#include "vtkPolyDataAlgorithm.h" + +class vtkMedicalImageProperties; +class vtkRTStructSetProperties; +//BTX +namespace gdcm { class Reader; } +//ETX +class VTK_EXPORT vtkGDCMPolyDataReader : public vtkPolyDataAlgorithm +{ +public: + static vtkGDCMPolyDataReader *New(); + vtkTypeRevisionMacro(vtkGDCMPolyDataReader,vtkPolyDataAlgorithm); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the filename of the file to be read + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Get the medical image properties object + vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties); + + vtkGetObjectMacro(RTStructSetProperties, vtkRTStructSetProperties); + +protected: + vtkGDCMPolyDataReader(); + ~vtkGDCMPolyDataReader(); + + char *FileName; + vtkMedicalImageProperties *MedicalImageProperties; + vtkRTStructSetProperties *RTStructSetProperties; +//BTX + void FillMedicalImageInformation(const gdcm::Reader &reader); +//ETX + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector); +//BTX + int RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader); + int RequestData_RTStructureSetStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector); + int RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & reader); + int RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector); +//ETX + +private: + vtkGDCMPolyDataReader(const vtkGDCMPolyDataReader&); // Not implemented. + void operator=(const vtkGDCMPolyDataReader&); // Not implemented. +}; + +#endif -- 2.47.1