]> Creatis software - clitk.git/commitdiff
From gdcm 1.x to gdcm 2.0
authordelmon <delmon>
Tue, 29 Mar 2011 13:14:10 +0000 (13:14 +0000)
committerdelmon <delmon>
Tue, 29 Mar 2011 13:14:10 +0000 (13:14 +0000)
common/clitkDicomRTDoseIO.cxx
common/clitkDicomRTDoseIO.h
common/clitkImageCommon.cxx
common/clitkImageCommon.h
common/vtkGDCMPolyDataReader.cxx [new file with mode: 0644]
common/vtkGDCMPolyDataReader.h [new file with mode: 0644]

index 6e3eba09342a4864220d71ae162e9ec0dd46f5e6..02d953e3a74eebadba37025b7d510f8257691437 100644 (file)
 #include "clitkCommon.h"
 
 // itk include
-#include <gdcmFileHelper.h>
+#if GDCM_MAJOR_VERSION == 2
+  #include <gdcmReader.h>
+  #include <gdcmAttribute.h>
+#else
+  #include <gdcmFileHelper.h>
+#endif
 
 #define GFOV_SPACING_TOL (1e-1)
 
 // 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; i<GetNumberOfDimensions(); i++)
     npix *= GetDimensions(i);
 
   /* PixelData */
+#if GDCM_MAJOR_VERSION == 2
+  gdcm::Image &i = m_GdcmImageReader.GetImage();
+  i.GetBuffer((char*)buffer);
+#else
+  float *img = (float*) buffer;
+
   gdcm::FileHelper m_GdcmFile_helper (m_GdcmFile);
 
   //size_t image_data_size = m_GdcmFile_helper.GetImageDataSize();
@@ -211,6 +294,8 @@ void clitk::DicomRTDoseIO::Read(void * buffer)
     itkExceptionMacro(<< "Error RTDOSE not type 16U and 32U (type="
                       << m_GdcmFile->GetPixelType().c_str() << ")");
   }
+  delete m_GdcmFile;
+#endif
 
   /* GCS FIX: Do I need to do something about endian-ness? */
 
@@ -221,8 +306,6 @@ void clitk::DicomRTDoseIO::Read(void * buffer)
 //   for (i = 0; i < vol->npix; i++) {
   //img[i] = image_data[i] * m_DoseScaling;
 //   }
-
-  delete m_GdcmFile;
 }
 
 //--------------------------------------------------------------------
index b5679aa133a056b3a9e517a2c4747ba898628883..dc09455a7c39cf59fe674ddfa7a2eac82abcf312 100644 (file)
@@ -24,6 +24,9 @@
 // itk include
 #include <itkImageIOBase.h>
 #include <gdcmFile.h>
+#if GDCM_MAJOR_VERSION == 2
+  #include <gdcmImageReader.h>
+#endif
 
 // std include
 #include <fstream>
@@ -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
 
index cfcbbe34225b3034adab9770bf127e92bfeb1f69..f5a8d3c813fbdc1e873693369e29f032e4ae6117 100644 (file)
@@ -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<gdcm::File> 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
 }
 ///--------------------------------------------------------------------
 
index 9e61223e0ab77484ed6566f1c0f91c2bea4fb0b7..38800c4c8e4796aae31254da5ac0cf6b9578b5bc 100644 (file)
 #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 (file)
index 0000000..b7062ec
--- /dev/null
@@ -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<gdcm::VR::DS,gdcm::VM::VM1_n> 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<gdcm::VR::DS,gdcm::VM::VM1_n> 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<gdcm::VR::LO,gdcm::VM::VM1_n> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> sqi = roicsq.GetValueAsSQ();
+  if( !sqi || !sqi->GetNumberOfItems() )
+    {
+    return 0;
+    }
+  const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
+  //const gdcm::SequenceOfItems *ssqi = ssroisq.GetSequenceOfItems();
+  gdcm::SmartPointer<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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<gdcm::SequenceOfItems> 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 (file)
index 0000000..6fe90bd
--- /dev/null
@@ -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