[ITK] [ITK-users] Limitations on GDCMImageIO

Emiliano Beronich emilianoberonich at gmail.com
Fri Mar 10 11:19:06 EST 2017


Hi everyone,

While using the GDCMImageIO class to write a Dicom Image, I found some
limitations so I modified the class to correct them.
The limitations I found are:
1) Can't write a sequence or even less Sequence inside Sequences.
2) Can't write arrays of unsigned short (Example: (0054,0010)
EnergyWindowVector, (0054,0020) DetectorVector, (0054,0080) SliceVector).

In order to pass the data the array of unsigned short I'm using a
std::vector<unsigned short>. The sequences are stored in a Dictionary.

Attached is the class modified. I would be great to include these changes
in future versions or improve GDCMImageIO class to correct these
limitations.

HTH,
Emiliano Beronich
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/community/attachments/20170310/aadf4f48/attachment-0001.html>
-------------- next part --------------
/*=========================================================================
*
*  Copyright Insight Software Consortium
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0.txt
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*=========================================================================*/
/*=========================================================================
*
*  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
*
*  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
*
*  For complete copyright, license and disclaimer of warranty information
*  please refer to the NOTICE file at the top of the ITK source tree.
*
*=========================================================================*/

#include "itkVersion.h"
#include "itkGDCMImageIO.h"
#include "itkIOCommon.h"
#include "itkArray.h"
#include "itkByteSwapper.h"
#include "vnl/vnl_cross.h"

#include "itkMetaDataObject.h"

#include "itksys/SystemTools.hxx"
#include "itksys/Base64.h"

#include "gdcmImageHelper.h"
#include "gdcmFileExplicitFilter.h"
#include "gdcmImageChangeTransferSyntax.h"
#include "gdcmDataSetHelper.h"
#include "gdcmStringFilter.h"
#include "gdcmImageApplyLookupTable.h"
#include "gdcmImageChangePlanarConfiguration.h"
#include "gdcmRescaler.h"
#include "gdcmImageReader.h"
#include "gdcmImageWriter.h"
#include "gdcmUIDGenerator.h"
#include "gdcmAttribute.h"
#include "gdcmGlobal.h"

#include <fstream>

namespace itk
{
  class InternalHeader
  {
  public:
    InternalHeader():m_Header(0) {}
    ~InternalHeader()
    {
      delete m_Header;
    }
    gdcm::File *m_Header;
  };

  GDCMImageIO::GDCMImageIO()
  {
    this->m_DICOMHeader = new InternalHeader;
    this->SetNumberOfDimensions(3); //needed for getting the 3 coordinates of
    // the origin, even if it is a 2D slice.
    m_ByteOrder = LittleEndian;     //default
    m_FileType = Binary;            //default...always true
    m_RescaleSlope = 1.0;
    m_RescaleIntercept = 0.0;
    // UIDPrefix is the ITK root id tacked with a ".1"
    // allowing to designate a subspace of the id space for ITK generated DICOM
    m_UIDPrefix = "1.2.826.0.1.3680043.2.1125." "1";

    // Purely internal use, no user access:
    m_StudyInstanceUID = "";
    m_SeriesInstanceUID = "";
    m_FrameOfReferenceInstanceUID = "";

    m_KeepOriginalUID = false;

    m_LoadPrivateTags = false;

    m_InternalComponentType = UNKNOWNCOMPONENTTYPE;

    // by default assume that images will be 2D.
    // This number is updated according the information
    // received through the MetaDataDictionary
    m_GlobalNumberOfDimensions = 2;
    // By default use JPEG2000. For legacy system, one should prefer JPEG since
    // JPEG2000 was only recently added to the DICOM standard
    m_CompressionType = JPEG2000;
  }

  GDCMImageIO::~GDCMImageIO()
  {
    delete this->m_DICOMHeader;
  }

  bool GDCMImageIO::OpenGDCMFileForReading(std::ifstream & os,
    const char *filename)
  {
    // Make sure that we have a file to
    if ( *filename == 0 )
    {
      itkExceptionMacro(<< "A FileName must be specified.");
    }

    // Close file from any previous image
    if ( os.is_open() )
    {
      os.close();
    }

    // Open the new file for reading
    itkDebugMacro(<< "Initialize: opening file " << filename);

    // Actually open the file
    os.open(filename, std::ios::in | std::ios::binary);

    if ( os.fail() )
    {
      return false;
    }

    return true;
  }

  bool GDCMImageIO::OpenGDCMFileForWriting(std::ofstream & os,
    const char *filename)
  {
    // Make sure that we have a file to
    if ( *filename == 0 )
    {
      itkExceptionMacro(<< "A FileName must be specified.");
    }

    // Close file from any previous image
    if ( os.is_open() )
    {
      os.close();
    }

    // Open the new file for writing
    itkDebugMacro(<< "Initialize: opening file " << filename);

    // Actually open the file
    os.open(filename, std::ios::out | std::ios::binary);

    if ( os.fail() )
    {
      itkExceptionMacro( << "Could not open file: "
        << filename << " for writing."
        << std::endl
        << "Reason: "
        << itksys::SystemTools::GetLastSystemError() );
    }

    return true;
  }

  // This method will only test if the header looks like a
  // GDCM image file.
  bool GDCMImageIO::CanReadFile(const char *filename)
  {
    std::ifstream file;
    std::string   fname(filename);

    if (  fname == "" )
    {
      itkDebugMacro(<< "No filename specified.");
      return false;
    }

    //Check for file existence:
    if ( !this->OpenGDCMFileForReading(file, filename) )
    {
      return false;
    }
    //
    // sniff for the DICM signature first at 128
    // then at zero, and if either place has it then
    // ask GDCM to try reading it.
    //
    // There isn't a definitive way to check for DICOM files;
    // This was actually cribbed from DICOMParser in VTK
    bool dicomsig(false);
    for(long int off = 128; off >= 0; off -= 128)
    {
      file.seekg(off,std::ios_base::beg);
      if(file.fail() || file.eof())
      {
        return false;
      }
      char buf[5];
      file.read(buf,4);
      if(file.fail())
      {
        return false;
      }
      buf[4] = '\0';
      std::string sig(buf);
      if(sig == "DICM")
      {
        dicomsig = true;
      }
    }
    if(!dicomsig)
    {
      file.seekg(0,std::ios_base::beg);
      unsigned short groupNo;
      file.read(reinterpret_cast<char *>(&groupNo),sizeof(unsigned short));
      ByteSwapper<unsigned short>::SwapFromSystemToLittleEndian(&groupNo);
      if(groupNo == 0x0002 || groupNo == 0x0008)
      {
        dicomsig = true;
      }
    }
    if(dicomsig)
    {
      // Check to see if its a valid dicom file gdcm is able to parse:
      // We are parsing the header one time here:
      gdcm::ImageReader reader;
      reader.SetFileName(filename);
      if ( reader.Read() )
      {
        return true;
      }
    }
    return false;
  }

  void GDCMImageIO::Read(void *pointer)
  {
    const char *filename = m_FileName.c_str();

    itkAssertInDebugAndIgnoreInReleaseMacro( gdcm::ImageHelper::GetForceRescaleInterceptSlope() );
    gdcm::ImageReader reader;
    reader.SetFileName(filename);
    if ( !reader.Read() )
    {
      itkExceptionMacro(<< "Cannot read requested file");
      return;
    }

    gdcm::Image & image = reader.GetImage();
#ifndef NDEBUG
    gdcm::PixelFormat pixeltype_debug = image.GetPixelFormat();
    itkAssertInDebugAndIgnoreInReleaseMacro(image.GetNumberOfDimensions() == 2 || image.GetNumberOfDimensions() == 3);
#endif
    SizeValueType len = image.GetBufferLength();

    // I think ITK only allow RGB image by pixel (and not by plane)
    if ( image.GetPlanarConfiguration() == 1 )
    {
      gdcm::ImageChangePlanarConfiguration icpc;
      icpc.SetInput(image);
      icpc.SetPlanarConfiguration(0);
      icpc.Change();
      image = icpc.GetOutput();
    }

    gdcm::PhotometricInterpretation pi = image.GetPhotometricInterpretation();
    if ( pi == gdcm::PhotometricInterpretation::PALETTE_COLOR )
    {
      gdcm::ImageApplyLookupTable ialut;
      ialut.SetInput(image);
      ialut.Apply();
      image = ialut.GetOutput();
      len *= 3;
    }

    if ( !image.GetBuffer( (char*)pointer ) )
    {
      itkExceptionMacro(<< "Failed to get the buffer!");
      return;
    }

    const gdcm::PixelFormat & pixeltype = image.GetPixelFormat();
#ifndef NDEBUG
    // ImageApplyLookupTable is meant to change the pixel type for PALETTE_COLOR images
    // (from single values to triple values per pixel)
    if ( pi != gdcm::PhotometricInterpretation::PALETTE_COLOR )
    {
      itkAssertInDebugAndIgnoreInReleaseMacro( pixeltype_debug == pixeltype );
    }
#endif

    if ( m_RescaleSlope != 1.0 || m_RescaleIntercept != 0.0 )
    {
      gdcm::Rescaler r;
      r.SetIntercept(m_RescaleIntercept);
      r.SetSlope(m_RescaleSlope);
      r.SetPixelFormat(pixeltype);
      gdcm::PixelFormat outputpt = r.ComputeInterceptSlopePixelType();
      char *            copy = new char[len];
      memcpy(copy, (char *)pointer, len);
      r.Rescale( (char *)pointer, copy, len );
      delete[] copy;
      // WARNING: sizeof(Real World Value) != sizeof(Stored Pixel)
      len = len * outputpt.GetPixelSize() / pixeltype.GetPixelSize();
    }

#ifndef NDEBUG
    // \postcondition
    // Now that len was updated (after unpacker 12bits -> 16bits, rescale...) ,
    // can now check compat:
    const SizeValueType numberOfBytesToBeRead =
      static_cast< SizeValueType >( this->GetImageSizeInBytes() );
    itkAssertInDebugAndIgnoreInReleaseMacro(numberOfBytesToBeRead == len);   // programmer error
#endif
  }


  void GDCMImageIO::InternalReadImageInformation(std::ifstream & file)
  {
    //read header
    if ( !this->OpenGDCMFileForReading( file, m_FileName.c_str() ) )
    {
      itkExceptionMacro(<< "Cannot read requested file");
    }

    // In general this should be relatively safe to assume
    gdcm::ImageHelper::SetForceRescaleInterceptSlope(true);

    const char *      filename = m_FileName.c_str();
    gdcm::ImageReader reader;
    reader.SetFileName(filename);
    if ( !reader.Read() )
    {
      itkExceptionMacro(<< "Cannot read requested file");
    }
    const gdcm::Image &   image = reader.GetImage();
    const gdcm::File &    f = reader.GetFile();
    const gdcm::DataSet & ds = f.GetDataSet();
    const unsigned int *  dims = image.GetDimensions();

    const gdcm::PixelFormat & pixeltype = image.GetPixelFormat();

    m_RescaleIntercept = image.GetIntercept();
    m_RescaleSlope = image.GetSlope();
    gdcm::Rescaler r;
    r.SetIntercept(m_RescaleIntercept);
    r.SetSlope(m_RescaleSlope);
    r.SetPixelFormat(pixeltype);
    gdcm::PixelFormat::ScalarType outputpt = r.ComputeInterceptSlopePixelType();

    itkAssertInDebugAndIgnoreInReleaseMacro(pixeltype <= outputpt);

    m_ComponentType = UNKNOWNCOMPONENTTYPE;
    switch ( outputpt )
    {
    case gdcm::PixelFormat::INT8:
      m_ComponentType = ImageIOBase::CHAR; // Is it signed char ?
      break;
    case gdcm::PixelFormat::UINT8:
      m_ComponentType = ImageIOBase::UCHAR;
      break;
      /* INT12 / UINT12 should not happen anymore in any modern DICOM */
    case gdcm::PixelFormat::INT12:
      m_ComponentType = ImageIOBase::SHORT;
      break;
    case gdcm::PixelFormat::UINT12:
      m_ComponentType = ImageIOBase::USHORT;
      break;
    case gdcm::PixelFormat::INT16:
      m_ComponentType = ImageIOBase::SHORT;
      break;
    case gdcm::PixelFormat::UINT16:
      m_ComponentType = ImageIOBase::USHORT;
      break;
      // RT / SC have 32bits
    case gdcm::PixelFormat::INT32:
      m_ComponentType = ImageIOBase::INT;
      break;
    case gdcm::PixelFormat::UINT32:
      m_ComponentType = ImageIOBase::UINT;
      break;
      //case gdcm::PixelFormat::FLOAT16: // TODO
    case gdcm::PixelFormat::FLOAT32:
      m_ComponentType = ImageIOBase::FLOAT;
      break;
    case gdcm::PixelFormat::FLOAT64:
      m_ComponentType = ImageIOBase::DOUBLE;
      break;
    default:
      itkExceptionMacro("Unhandled PixelFormat: " << outputpt);
    }

    m_NumberOfComponents = pixeltype.GetSamplesPerPixel();
    if ( image.GetPhotometricInterpretation() ==
      gdcm::PhotometricInterpretation::PALETTE_COLOR )
    {
      itkAssertInDebugAndIgnoreInReleaseMacro(m_NumberOfComponents == 1);
      // TODO: need to do the LUT ourself...
      //itkExceptionMacro(<< "PALETTE_COLOR is not implemented yet");
      // AFAIK ITK user don't care about the palette so always apply it and fake a
      // RGB image for them
      m_NumberOfComponents = 3;
    }
    if ( m_NumberOfComponents == 1 )
    {
      this->SetPixelType(SCALAR);
    }
    else
    {
      this->SetPixelType(RGB); // What if image is YBR ? This is a problem since
      // integer conversion is lossy
    }

    // set values in case we don't find them
    //this->SetNumberOfDimensions(  image.GetNumberOfDimensions() );
    m_Dimensions[0] = dims[0];
    m_Dimensions[1] = dims[1];

    const double *spacing = image.GetSpacing();
    m_Spacing[0] = spacing[0];
    m_Spacing[1] = spacing[1];
    m_Spacing[2] = spacing[2];

    const double *origin = image.GetOrigin();
    m_Origin[0] = origin[0];
    m_Origin[1] = origin[1];
    m_Origin[2] = origin[2];

    if ( image.GetNumberOfDimensions() == 3 )
    {
      m_Dimensions[2] = dims[2];
    }
    else
    {
      m_Dimensions[2] = 1;
    }

    const double *       dircos = image.GetDirectionCosines();
    vnl_vector< double > rowDirection(3), columnDirection(3);
    rowDirection[0] = dircos[0];
    rowDirection[1] = dircos[1];
    rowDirection[2] = dircos[2];

    columnDirection[0] = dircos[3];
    columnDirection[1] = dircos[4];
    columnDirection[2] = dircos[5];

    vnl_vector< double > sliceDirection = vnl_cross_3d(rowDirection, columnDirection);

    // orthogonalize
    sliceDirection.normalize();
    rowDirection = vnl_cross_3d(columnDirection,sliceDirection).normalize();
    columnDirection = vnl_cross_3d(sliceDirection,rowDirection);

    this->SetDirection(0, rowDirection);
    this->SetDirection(1, columnDirection);
    this->SetDirection(2, sliceDirection);

    //Now copying the gdcm dictionary to the itk dictionary:
    MetaDataDictionary & dico = this->GetMetaDataDictionary();

    // in the case of re-use by ImageSeriesReader, clear the dictionary
    // before populating it.
    dico.Clear();

    gdcm::StringFilter sf;
    sf.SetFile(f);
    gdcm::DataSet::ConstIterator it = ds.Begin();

    // Copy of the header->content
    for (; it != ds.End(); ++it )
    {
      const gdcm::DataElement & ref = *it;
      const gdcm::Tag &         tag = ref.GetTag();
      // Compute VR from the toplevel file, and the currently processed dataset:
      gdcm::VR vr = gdcm::DataSetHelper::ComputeVR(f, ds, tag);

      // Process binary field and encode them as mime64: only when we do not know
      // of any better
      // representation. VR::US is binary, but user want ASCII representation.
      if ( vr & ( gdcm::VR::OB | gdcm::VR::OF | gdcm::VR::OW | gdcm::VR::SQ | gdcm::VR::UN ) )
      {
        // itkAssertInDebugAndIgnoreInReleaseMacro( vr & gdcm::VR::VRBINARY );
        /*
        * Old behavior was to skip SQ, Pixel Data element. I decided that it is not safe to mime64
        * VR::UN element. There used to be a bug in gdcm 1.2.0 and VR:UN element.
        */
        if ( (m_LoadPrivateTags || tag.IsPublic()) && vr != gdcm::VR::SQ
          && tag != gdcm::Tag(0x7fe0, 0x0010) /* && vr != gdcm::VR::UN*/ )
        {
          const gdcm::ByteValue *bv = ref.GetByteValue();
          if ( bv )
          {
            // base64 streams have to be a multiple of 4 bytes in length
            int encodedLengthEstimate = 2 * bv->GetLength();
            encodedLengthEstimate = ( ( encodedLengthEstimate / 4 ) + 1 ) * 4;

            char *       bin = new char[encodedLengthEstimate];
            unsigned int encodedLengthActual = static_cast< unsigned int >(
              itksysBase64_Encode(
              (const unsigned char *)bv->GetPointer(),
              static_cast< SizeValueType >( bv->GetLength() ),
              (unsigned char *)bin,
              static_cast< int >( 0 ) ) );
            std::string encodedValue(bin, encodedLengthActual);
            EncapsulateMetaData< std::string >(dico, tag.PrintAsPipeSeparatedString(), encodedValue);
            delete[] bin;
          }
        }
      }
      else /* if ( vr & gdcm::VR::VRASCII ) */
      {
        // Only copying field from the public DICOM dictionary
        if ( m_LoadPrivateTags || tag.IsPublic() )
        {
          EncapsulateMetaData< std::string >( dico, tag.PrintAsPipeSeparatedString(), sf.ToString(tag) );
        }
      }
    }

#if defined( ITKIO_DEPRECATED_GDCM1_API )
    // Now is a good time to fill in the class member:
    char name[512];
    this->GetPatientName(name);
    this->GetPatientID(name);
    this->GetPatientSex(name);
    this->GetPatientAge(name);
    this->GetStudyID(name);
    this->GetPatientDOB(name);
    this->GetStudyDescription(name);
    this->GetBodyPart(name);
    this->GetNumberOfSeriesInStudy(name);
    this->GetNumberOfStudyRelatedSeries(name);
    this->GetStudyDate(name);
    this->GetModality(name);
    this->GetManufacturer(name);
    this->GetInstitution(name);
    this->GetModel(name);
    this->GetScanOptions(name);
#endif
  }

  void GDCMImageIO::ReadImageInformation()
  {
    std::ifstream file;

    this->InternalReadImageInformation(file);
  }

  bool GDCMImageIO::CanWriteFile(const char *name)
  {
    std::string filename = name;

    if (  filename == "" )
    {
      itkDebugMacro(<< "No filename specified.");
      return false;
    }

    std::string::size_type dcmPos = filename.rfind(".dcm");
    if ( ( dcmPos != std::string::npos )
      && ( dcmPos == filename.length() - 4 ) )
    {
      return true;
    }

    dcmPos = filename.rfind(".DCM");
    if ( ( dcmPos != std::string::npos )
      && ( dcmPos == filename.length() - 4 ) )
    {
      return true;
    }

    std::string::size_type dicomPos = filename.rfind(".dicom");
    if ( ( dicomPos != std::string::npos )
      && ( dicomPos == filename.length() - 6 ) )
    {
      return true;
    }

    dicomPos = filename.rfind(".DICOM");
    if ( ( dicomPos != std::string::npos )
      && ( dicomPos == filename.length() - 6 ) )
    {
      return true;
    }

    return false;
  }

  void GDCMImageIO::WriteImageInformation()
  {}

  void GDCMImageIO::ReadElement(itk::MetaDataDictionary& dict, gdcm::Tag& tag, const std::string& key, gdcm::DataSet& dataset, gdcm::FileMetaInformation& fmi)
  {
    gdcm::Global &      g = gdcm::Global::GetInstance();
    const gdcm::Dicts & dicts = g.GetDicts();
    const gdcm::Dict &  pubdict = dicts.GetPublicDict();
    const gdcm::DictEntry & dictEntry = pubdict.GetDictEntry(tag);
    gdcm::VR::VRType        vrtype = dictEntry.GetVR();
    if ( vrtype & ( gdcm::VR::OB | gdcm::VR::OF | gdcm::VR::OW | gdcm::VR::UN ) )
    {
      std::string value;
      ExposeMetaData< std::string >(dict, key, value);
      // Custom VR::VRBINARY
      // convert value from Base64
      uint8_t *    bin = new uint8_t[value.size()];
      unsigned int decodedLengthActual = static_cast< unsigned int >(
        itksysBase64_Decode(
        (const unsigned char *)value.c_str(),
        static_cast< SizeValueType >( 0 ),
        (unsigned char *)bin,
        static_cast< SizeValueType >( value.size() ) ) );
      if ( /*tag.GetGroup() != 0 ||*/ tag.GetElement() != 0 ) // ?
      {
        gdcm::DataElement de(tag);
        de.SetByteValue( (char *)bin, decodedLengthActual );
        de.SetVR( dictEntry.GetVR() );
        if ( tag.GetGroup() == 0x2 ) fmi.Insert(de);
        else dataset.Insert(de);
      }
      delete[] bin;
    } else if (vrtype & gdcm::VR::US) {
      std::vector< unsigned short> vectorValue;
      ExposeMetaData< std::vector <unsigned short> >(dict, key, vectorValue);
      if (vectorValue.size() > 0) {
        if ( !tag.IsGroupLength() ) // Get rid of group length, they are not useful
        {
          gdcm::DataElement de(tag);
          if ( dictEntry.GetVR().IsVRFile() )
          {
            de.SetVR( dictEntry.GetVR() );
          }
          de.SetByteValue( (char*) &vectorValue[0], static_cast<uint32_t>(sizeof(unsigned short) * vectorValue.size()) );
          dataset.Insert(de); 
        }
      } else {
        unsigned short value;
        ExposeMetaData< unsigned short >(dict, key, value);
        if ( !tag.IsGroupLength() ) // Get rid of group length, they are not useful
        {
          gdcm::DataElement de(tag);
          if ( dictEntry.GetVR().IsVRFile() )
          {
            de.SetVR( dictEntry.GetVR() );
          }
          de.SetByteValue( (char*) &value, sizeof(unsigned short) );
          dataset.Insert(de);   //value, tag.GetGroup(), tag.GetElement());
        }

      }
    } else // VRASCII
    {
      std::string value;
      ExposeMetaData< std::string >(dict, key, value);
      // TODO, should we keep:
      // (0028,0106) US/SS 0                                        #2, 1
      // SmallestImagePixelValue
      // (0028,0107) US/SS 4095                                     #2, 1
      // LargestImagePixelValue
      if ( !tag.IsGroupLength() ) // Get rid of group length, they are not useful
      {
        gdcm::DataElement de(tag);
        if ( dictEntry.GetVR().IsVRFile() )
        {
          de.SetVR( dictEntry.GetVR() );
        }
#if GDCM_MAJOR_VERSION == 2 && GDCM_MINOR_VERSION <= 12
        // This will not work in the vast majority of cases but to get at
        // least something working in GDCM 2.0.12
        de.SetByteValue( value.c_str(), static_cast<uint32_t>(value.size()) );
#else
        std::string si = sf.FromString( tag, value.c_str(), value.size() );
        de.SetByteValue( si.c_str(), si.size() );
#endif
        if ( tag.GetGroup() == 0x2 ) 
          fmi.Insert(de);
        else 
          dataset.Insert(de);   //value, tag.GetGroup(), tag.GetElement());
      }
    }  
  }

  void GDCMImageIO::ReadSequenceElement( itk::MetaDataDictionary& dict, const std::string& key, gdcm::Tag& tag, gdcm::DataSet& dataset,  gdcm::FileMetaInformation & fmi)
  {
    gdcm::Global &      g = gdcm::Global::GetInstance();
    const gdcm::Dicts & dicts = g.GetDicts();
    const gdcm::Dict &  pubdict = dicts.GetPublicDict();
    const gdcm::DictEntry & dictEntry = pubdict.GetDictEntry(tag);
    gdcm::VR::VRType        vrtype = dictEntry.GetVR();
    itk::MetaDataDictionary seqDict;
    ExposeMetaData< itk::MetaDataDictionary >(dict, key, seqDict);
    gdcm::SmartPointer<gdcm::SequenceOfItems> sq = new gdcm::SequenceOfItems();
    sq->SetLengthToUndefined();
    gdcm::Item item;
    gdcm::DataSet &nds = item.GetNestedDataSet();

    gdcm::Tag            tagSq;
    std::string          valueSq;
    itk::MetaDataDictionary::ConstIterator itrSq = seqDict.Begin();
    itk::MetaDataDictionary::ConstIterator endSq = seqDict.End();

    while ( itrSq != endSq )
    {
      const std::string & keySq = itrSq->first; //Needed for bcc32
      ExposeMetaData< std::string >(seqDict, keySq, valueSq);

      // Convert DICOM name to DICOM (group,element)
      bool b = tagSq.ReadFromPipeSeparatedString( keySq.c_str() );
      if (b) 
      {
        const gdcm::DictEntry & seqDictEntry = pubdict.GetDictEntry(tagSq);
        gdcm::VR::VRType        vrtype = seqDictEntry.GetVR();
        if ( vrtype == gdcm::VR::SQ )
        {
          // How did we reach here 
          // Create a Sequence
          ReadSequenceElement(seqDict, keySq, tagSq, dataset, fmi);
        }
        else  {
          ReadElement(seqDict, tagSq, keySq, nds, fmi);
        }
      }
      ++itrSq;
    }
    sq->AddItem(item);
    gdcm::DataElement des( tag );
    des.SetVR(gdcm::VR::SQ);
    des.SetValue(*sq);
    des.SetVLToUndefined();
    dataset.Insert(des);
  }

  void GDCMImageIO::Write(const void *buffer)
  {
    std::ofstream file;

    if ( !this->OpenGDCMFileForWriting( file, m_FileName.c_str() ) )
    {
      return;
    }
    file.close();
    // global static:
    gdcm::UIDGenerator::SetRoot( m_UIDPrefix.c_str() );

    // echo "ITK" | od -b
    gdcm::FileMetaInformation::AppendImplementationClassUID("111.124.113");
    const std::string project_name = std::string("GDCM/ITK ") + itk::Version::GetITKVersion();
    gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( project_name.c_str() );

    gdcm::ImageWriter   writer;
    gdcm::FileMetaInformation &     fmi = writer.GetFile().GetHeader();
    gdcm::DataSet &     header = writer.GetFile().GetDataSet();
    gdcm::Global &      g = gdcm::Global::GetInstance();
    const gdcm::Dicts & dicts = g.GetDicts();
    const gdcm::Dict &  pubdict = dicts.GetPublicDict();

    std::string          value;
    MetaDataDictionary & dict = this->GetMetaDataDictionary();
    gdcm::Tag            tag;
    //Smarter approach using real iterators
    itk::MetaDataDictionary::ConstIterator itr = dict.Begin();
    itk::MetaDataDictionary::ConstIterator end = dict.End();
    gdcm::StringFilter                     sf;
    sf.SetFile( writer.GetFile() );

    while ( itr != end )
    {
      const std::string & key = itr->first; //Needed for bcc32

      // Convert DICOM name to DICOM (group,element)
      bool b = tag.ReadFromPipeSeparatedString( key.c_str() );

      // Anything that has been changed in the MetaData Dict will be pushed
      // into the DICOM header:
      if ( b /*tag != gdcm::Tag(0xffff,0xffff)*/ /*dictEntry*/ )
      {
        const gdcm::DictEntry & dictEntry = pubdict.GetDictEntry(tag);
        gdcm::VR::VRType        vrtype = dictEntry.GetVR();
        if ( dictEntry.GetVR() == gdcm::VR::SQ )
        {
          // Insert sequence into data set
          ReadSequenceElement(dict, key, tag, header, fmi);
        }
        else {
          ReadElement(dict, tag, key, header, fmi);
        }
      }
      else
      {
        // This is not a DICOM entry, then check if it is one of the
        // ITK standard ones
        if ( key == ITK_NumberOfDimensions )
        {
          unsigned int numberOfDimensions = 0;
          ExposeMetaData< unsigned int >(dict, key, numberOfDimensions);
          m_GlobalNumberOfDimensions = numberOfDimensions;
          m_Origin.resize(m_GlobalNumberOfDimensions);
          m_Spacing.resize(m_GlobalNumberOfDimensions);
          m_Direction.resize(m_GlobalNumberOfDimensions);
          for (unsigned int i = 0; i < m_GlobalNumberOfDimensions; i++)
          {
            m_Direction[i].resize(m_GlobalNumberOfDimensions);
          }
        }
        else if ( key == ITK_Origin )
        {
          typedef Array< double > DoubleArrayType;
          DoubleArrayType originArray;
          ExposeMetaData< DoubleArrayType >(dict, key, originArray);
          m_Origin[0] = originArray[0];
          m_Origin[1] = originArray[1];
          m_Origin[2] = originArray[2];
        }
        else if ( key == ITK_Spacing )
        {
          typedef Array< double > DoubleArrayType;
          DoubleArrayType spacingArray;
          ExposeMetaData< DoubleArrayType >(dict, key, spacingArray);
          m_Spacing[0] = spacingArray[0];
          m_Spacing[1] = spacingArray[1];
          m_Spacing[2] = spacingArray[2];
        }
        else if( key == ITK_ZDirection )
        {
          typedef Matrix< double > DoubleMatrixType;
          DoubleMatrixType directionMatrix;
          ExposeMetaData< DoubleMatrixType >( dict, key, directionMatrix );
          for(int i = 0; i<3; i++)
          {
            for(int j = 0; j<3; j++)
            {
              m_Direction[i][j]=directionMatrix[i][j];
            }
          }
        }
        else
        {
          itkDebugMacro(
            << "GDCMImageIO: non-DICOM and non-ITK standard key = " << key);
        }
      }

      ++itr;
    }
    //std::cout << header << std::endl;

    //this->SetNumberOfDimensions(3);
    //gdcm::Image &image = writer.GetImage();
    gdcm::SmartPointer< gdcm::Image > simage = new gdcm::Image;
    gdcm::Image &                     image = *simage;
    image.SetNumberOfDimensions(2);   // good default
    image.SetDimension(0, static_cast<unsigned int>(m_Dimensions[0]));
    image.SetDimension(1, static_cast<unsigned int>(m_Dimensions[1]));
    //image.SetDimension(2, m_Dimensions[2] );
    image.SetSpacing(0, m_Spacing[0]);
    image.SetSpacing(1, m_Spacing[1]);
    if ( m_NumberOfDimensions > 2 && m_Dimensions[2] != 1 )
    {
      image.SetSpacing(2, m_Spacing[2]);
    }
    // Set the origin (image position patient)
    // If the meta dictionary contains the tag "0020 0032", use it
    std::string tempString;
    const bool hasIPP = ExposeMetaData<std::string>(dict,"0020|0032",tempString);
    if( hasIPP)
    {
      double origin3D[3];
      sscanf(tempString.c_str(), "%lf\\%lf\\%lf", &(origin3D[0]), &(origin3D[1]), &(origin3D[2]) );
      image.SetOrigin(0, origin3D[0]);
      image.SetOrigin(1, origin3D[1]);
      image.SetOrigin(2, origin3D[2]);
    }
    else
    {
      image.SetOrigin(0, m_Origin[0]);
      image.SetOrigin(1, m_Origin[1]);
      if ( m_Origin.size() == 3 )
      {
        image.SetOrigin(2, m_Origin[2]);
      }
      else
      {
        image.SetOrigin(2, 0);
      }
    }
    if ( m_NumberOfDimensions > 2 && m_Dimensions[2] != 1 )
    {
      // resize num of dim to 3:
      image.SetNumberOfDimensions(3);
      image.SetDimension(2, static_cast<unsigned int>(m_Dimensions[2]));
    }

    // Do the direction now:
    // if the meta dictionary contains the tag "0020 0037", use it
    const bool hasIOP = ExposeMetaData<std::string>(dict, "0020|0037",tempString);
    if (hasIOP)
    {
      double directions[6];
      sscanf(tempString.c_str(), "%lf\\%lf\\%lf\\%lf\\%lf\\%lf", &(directions[0]), &(directions[1]), &(directions[2]),&(directions[3]),&(directions[4]),&(directions[5]));
      image.SetDirectionCosines(0, directions[0]);
      image.SetDirectionCosines(1, directions[1]);
      image.SetDirectionCosines(2, directions[2]);
      image.SetDirectionCosines(3, directions[3]);
      image.SetDirectionCosines(4, directions[4]);
      image.SetDirectionCosines(5, directions[5]);
    }
    else
    {
      image.SetDirectionCosines(0, m_Direction[0][0]);
      image.SetDirectionCosines(1, m_Direction[0][1]);
      if ( m_Direction.size() == 3 )
      {
        image.SetDirectionCosines(2, m_Direction[0][2]);
      }
      else
      {
        image.SetDirectionCosines(2, 0);
      }
      image.SetDirectionCosines(3, m_Direction[1][0]);
      image.SetDirectionCosines(4, m_Direction[1][1]);
      if ( m_Direction.size() == 3 )
      {
        image.SetDirectionCosines(5, m_Direction[1][2]);
      }
      else
      {
        image.SetDirectionCosines(5, 0);
      }
    }

    // reset any previous value:
    m_RescaleSlope = 1.0;
    m_RescaleIntercept = 0.0;

    // Get user defined rescale slope/intercept
    std::string rescaleintercept;
    ExposeMetaData< std::string >(dict, "0028|1052", rescaleintercept);
    std::string rescaleslope;
    ExposeMetaData< std::string >(dict, "0028|1053", rescaleslope);
    if ( rescaleintercept != "" && rescaleslope != "" )
    {
      itksys_ios::stringstream sstr1;
      sstr1 << rescaleintercept;
      if ( !( sstr1 >> m_RescaleIntercept ) )
      {
        itkExceptionMacro("Problem reading RescaleIntercept: " << rescaleintercept);
      }
      itksys_ios::stringstream sstr2;
      sstr2 << rescaleslope;
      if ( !( sstr2 >> m_RescaleSlope ) )
      {
        itkExceptionMacro("Problem reading RescaleSlope: " << rescaleslope);
      }
      // header->InsertValEntry( "US", 0x0028, 0x1054 ); // Rescale Type
    }
    else if ( rescaleintercept != "" || rescaleslope != "" ) // xor
    {
      itkExceptionMacro("Both RescaleSlope & RescaleIntercept need to be present");
    }

    // Handle the bitDepth:
    std::string bitsAllocated;
    std::string bitsStored;
    std::string highBit;
    std::string pixelRep;
    // Get user defined bit representation:
    ExposeMetaData< std::string >(dict, "0028|0100", bitsAllocated);
    ExposeMetaData< std::string >(dict, "0028|0101", bitsStored);
    ExposeMetaData< std::string >(dict, "0028|0102", highBit);
    ExposeMetaData< std::string >(dict, "0028|0103", pixelRep);

    gdcm::PixelFormat pixeltype = gdcm::PixelFormat::UNKNOWN;
    switch ( this->GetComponentType() )
    {
    case ImageIOBase::CHAR:
      pixeltype = gdcm::PixelFormat::INT8;
      break;
    case ImageIOBase::UCHAR:
      pixeltype = gdcm::PixelFormat::UINT8;
      break;
    case ImageIOBase::SHORT:
      pixeltype = gdcm::PixelFormat::INT16;
      break;
    case ImageIOBase::USHORT:
      pixeltype = gdcm::PixelFormat::UINT16;
      break;
    case ImageIOBase::INT:
      pixeltype = gdcm::PixelFormat::INT32;
      break;
    case ImageIOBase::UINT:
      pixeltype = gdcm::PixelFormat::UINT32;
      break;
      //Disabling FLOAT and DOUBLE for now...
    case ImageIOBase::FLOAT:
      pixeltype = gdcm::PixelFormat::FLOAT32;
      break;
    case ImageIOBase::DOUBLE:
      pixeltype = gdcm::PixelFormat::FLOAT64;
      break;
    default:
      itkExceptionMacro(<< "DICOM does not support this component type");
    }
    itkAssertInDebugAndIgnoreInReleaseMacro(pixeltype != gdcm::PixelFormat::UNKNOWN);
    gdcm::PhotometricInterpretation pi;
    if ( this->GetNumberOfComponents() == 1 )
    {
      pi = gdcm::PhotometricInterpretation::MONOCHROME2;
    }
    else if ( this->GetNumberOfComponents() == 3 )
    {
      pi = gdcm::PhotometricInterpretation::RGB;
      // (0028,0006) US 0                                        #2, 1
      // PlanarConfiguration
    }
    else
    {
      itkExceptionMacro(<< "DICOM does not support this component type");
    }
    pixeltype.SetSamplesPerPixel( static_cast<short unsigned int>( this->GetNumberOfComponents() ) );

    // Compute the outpixeltype
    gdcm::PixelFormat outpixeltype = gdcm::PixelFormat::UNKNOWN;
    if ( pixeltype == gdcm::PixelFormat::FLOAT32 || pixeltype == gdcm::PixelFormat::FLOAT64 )
    {
      if ( bitsAllocated != "" && bitsStored != "" && highBit != "" && pixelRep != "" )
      {
        outpixeltype.SetBitsAllocated( static_cast<unsigned short int>(atoi( bitsAllocated.c_str() ) ));
        outpixeltype.SetBitsStored( static_cast<unsigned short int>(atoi( bitsStored.c_str() )) );
        outpixeltype.SetHighBit( static_cast<unsigned short int>(atoi( highBit.c_str()) ) );
        outpixeltype.SetPixelRepresentation( static_cast<unsigned short int>(atoi( pixelRep.c_str() )) );
        if ( this->GetNumberOfComponents() != 1 )
        {
          itkExceptionMacro(<< "Sorry Dave I can't do that");
        }
        itkAssertInDebugAndIgnoreInReleaseMacro(outpixeltype != gdcm::PixelFormat::UNKNOWN);
      }
      else
      {
        itkExceptionMacro(<< "A Floating point buffer was passed but the stored pixel type was not specified."
          "This is currently not supported");
      }
    }

    image.SetPhotometricInterpretation(pi);
    if ( outpixeltype != gdcm::PixelFormat::UNKNOWN )
    {
      image.SetPixelFormat(outpixeltype);
    }
    else
    {
      image.SetPixelFormat(pixeltype);
    }
    SizeValueType len = image.GetBufferLength();

    size_t numberOfBytes = this->GetImageSizeInBytes();

    gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0, 0x0010) );
    // Handle rescaler here:
    // Whenever shift / scale is needed... do it !
    if( outpixeltype != gdcm::PixelFormat::UNKNOWN )
    {
      itkAssertInDebugAndIgnoreInReleaseMacro( m_RescaleIntercept != 0 || m_RescaleSlope != 1 );
      // rescale from float to unsigned short
      gdcm::Rescaler ir;
      ir.SetIntercept(m_RescaleIntercept);
      ir.SetSlope(m_RescaleSlope);
      ir.SetPixelFormat(pixeltype);
      ir.SetMinMaxForPixelType( static_cast<double>(outpixeltype.GetMin()), static_cast<double>(outpixeltype.GetMax()) );
      image.SetIntercept(m_RescaleIntercept);
      image.SetSlope(m_RescaleSlope);
      char *copy = new char[len];
      ir.InverseRescale(copy, (char *)buffer, numberOfBytes);
      pixeldata.SetByteValue(copy, static_cast<uint32_t>(len));
      delete[] copy;
    }
    else
    {
      itkAssertInDebugAndIgnoreInReleaseMacro(len == numberOfBytes);
      // only do a straight copy:
      pixeldata.SetByteValue( (char *)buffer, static_cast<unsigned int>(numberOfBytes) );
    }
    image.SetDataElement(pixeldata);

    // Handle compression here:
    // If user ask to use compression:
    if ( m_UseCompression )
    {
      gdcm::ImageChangeTransferSyntax change;
      if ( m_CompressionType == JPEG )
      {
        change.SetTransferSyntax(gdcm::TransferSyntax::JPEGLosslessProcess14_1);
      }
      else if ( m_CompressionType == JPEG2000 )
      {
        change.SetTransferSyntax(gdcm::TransferSyntax::JPEG2000Lossless);
      }
      else
      {
        itkExceptionMacro(<< "Unknown compression type");
      }
      change.SetInput(image);
      bool b = change.Change();
      if ( !b )
      {
        itkExceptionMacro(<< "Could not change the Transfer Syntax for Compression");
      }
      writer.SetImage( change.GetOutput() );
    }
    else
    {
      writer.SetImage(image);
    }

    if ( !m_KeepOriginalUID )
    {
      // UID generation part:
      // We only create *ONE* Study/Series.Frame of Reference Instance UID
      if ( m_StudyInstanceUID.empty() )
      {
        // As long as user maintain there gdcmIO they will keep the same
        // Study/Series instance UID.
        gdcm::UIDGenerator uid;
        m_StudyInstanceUID = uid.Generate();
        m_SeriesInstanceUID = uid.Generate();
        m_FrameOfReferenceInstanceUID = uid.Generate();
      }
      //std::string uid = uid.Generate();
      const char *studyuid = m_StudyInstanceUID.c_str();
      {
        gdcm::DataElement de( gdcm::Tag(0x0020, 0x000d) ); // Study
        de.SetByteValue( studyuid, static_cast<unsigned int>(strlen(studyuid)) );
        de.SetVR( gdcm::Attribute< 0x0020, 0x000d >::GetVR() );
        header.Insert(de);
      }
      const char *seriesuid = m_SeriesInstanceUID.c_str();
      {
        gdcm::DataElement de( gdcm::Tag(0x0020, 0x000e) ); // Series
        de.SetByteValue( seriesuid, static_cast<unsigned int>(strlen(seriesuid)) );
        de.SetVR( gdcm::Attribute< 0x0020, 0x000e >::GetVR() );
        header.Insert(de);
      }
      const char *frameofreferenceuid = m_FrameOfReferenceInstanceUID.c_str();
      {
        gdcm::DataElement de( gdcm::Tag(0x0020, 0x0052) ); // Frame of Reference
        de.SetByteValue( frameofreferenceuid, static_cast<unsigned int>(strlen( frameofreferenceuid)) );
        de.SetVR( gdcm::Attribute< 0x0020, 0x0052 >::GetVR() );
        header.Insert(de);
      }
    }

    if ( image.GetTransferSyntax() != gdcm::TransferSyntax::ImplicitVRLittleEndian )
    {
      gdcm::FileExplicitFilter fef;
      //fef.SetChangePrivateTags( true );
      fef.SetFile( writer.GetFile() );
      if ( !fef.Change() )
      {
        itkExceptionMacro(<< "Failed to change to Explicit Transfer Syntax");
      }
    }

    const char *filename = m_FileName.c_str();
    writer.SetFileName(filename);
    if ( !writer.Write() )
    {
      itkExceptionMacro(<< "DICOM does not support this component type");
    }
  }

#if defined( ITKIO_DEPRECATED_GDCM1_API )
  // Convenience methods to query patient and scanner information. These
  // methods are here for compatibility with the DICOMImageIO2 class.
  void GDCMImageIO::GetPatientName(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0010|0010", m_PatientName);
    strcpy ( name, m_PatientName.c_str() );
  }

  void GDCMImageIO::GetPatientID(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0010|0020", m_PatientID);
    strcpy ( name, m_PatientID.c_str() );
  }

  void GDCMImageIO::GetPatientSex(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0010|0040", m_PatientSex);
    strcpy ( name, m_PatientSex.c_str() );
  }

  void GDCMImageIO::GetPatientAge(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0010|1010", m_PatientAge);
    strcpy ( name, m_PatientAge.c_str() );
  }

  void GDCMImageIO::GetStudyID(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0020|0010", m_StudyID);
    strcpy ( name, m_StudyID.c_str() );
  }

  void GDCMImageIO::GetPatientDOB(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0010|0030", m_PatientDOB);
    strcpy ( name, m_PatientDOB.c_str() );
  }

  void GDCMImageIO::GetStudyDescription(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0008|1030", m_StudyDescription);
    strcpy ( name, m_StudyDescription.c_str() );
  }

  void GDCMImageIO::GetBodyPart(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0018|0015", m_BodyPart);
    strcpy ( name, m_BodyPart.c_str() );
  }

  void GDCMImageIO::GetNumberOfSeriesInStudy(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0020|1000", m_NumberOfSeriesInStudy);
    strcpy ( name, m_NumberOfSeriesInStudy.c_str() );
  }

  void GDCMImageIO::GetNumberOfStudyRelatedSeries(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0020|1206", m_NumberOfStudyRelatedSeries);
    strcpy ( name, m_NumberOfStudyRelatedSeries.c_str() );
  }

  void GDCMImageIO::GetStudyDate(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0008|0020", m_StudyDate);
    strcpy ( name, m_StudyDate.c_str() );
  }

  void GDCMImageIO::GetModality(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0008|0060", m_Modality);
    strcpy ( name, m_Modality.c_str() );
  }

  void GDCMImageIO::GetManufacturer(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0008|0070", m_Manufacturer);
    strcpy ( name, m_Manufacturer.c_str() );
  }

  void GDCMImageIO::GetInstitution(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0008|0080", m_Institution);
    strcpy ( name, m_Institution.c_str() );
  }

  void GDCMImageIO::GetModel(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0008|1090", m_Model);
    strcpy ( name, m_Model.c_str() );
  }

  void GDCMImageIO::GetScanOptions(char *name)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    ExposeMetaData< std::string >(dict, "0018|0022", m_ScanOptions);
    strcpy ( name, m_ScanOptions.c_str() );
  }
#endif

  bool GDCMImageIO::GetValueFromTag(const std::string & tag, std::string & value)
  {
    MetaDataDictionary & dict = this->GetMetaDataDictionary();

    std::string tag_lower = tag;
    std::transform( tag_lower.begin(), tag_lower.end(), tag_lower.begin(),
      static_cast<int(*)(int)>( ::tolower ) );

    return ExposeMetaData< std::string >(dict, tag_lower, value);
  }

  bool GDCMImageIO::GetLabelFromTag(const std::string & tag,
    std::string & labelId)
  {
    gdcm::Tag t;
    if ( t.ReadFromPipeSeparatedString( tag.c_str() ) && t.IsPublic() )
    {
      const gdcm::Global &    g = gdcm::Global::GetInstance();
      const gdcm::Dicts &     dicts = g.GetDicts();
      const gdcm::DictEntry & entry = dicts.GetDictEntry(t);
      labelId = entry.GetName();
      return true;
    }
    return false;
  }

  void GDCMImageIO::PrintSelf(std::ostream & os, Indent indent) const
  {
    Superclass::PrintSelf(os, indent);
    os << indent << "Internal Component Type: " << this->GetComponentTypeAsString(m_InternalComponentType)
      << std::endl;
    os << indent << "RescaleSlope: " << m_RescaleSlope << std::endl;
    os << indent << "RescaleIntercept: " << m_RescaleIntercept << std::endl;
    os << indent << "KeepOriginalUID:" << ( m_KeepOriginalUID ? "On" : "Off" ) << std::endl;
    os << indent << "LoadPrivateTags:" << ( m_LoadPrivateTags ? "On" : "Off" ) << std::endl;
    os << indent << "UIDPrefix: " << m_UIDPrefix << std::endl;
    os << indent << "StudyInstanceUID: " << m_StudyInstanceUID << std::endl;
    os << indent << "SeriesInstanceUID: " << m_SeriesInstanceUID << std::endl;
    os << indent << "FrameOfReferenceInstanceUID: " << m_FrameOfReferenceInstanceUID << std::endl;
    os << indent << "CompressionType:" << m_CompressionType << std::endl;

#if defined( ITKIO_DEPRECATED_GDCM1_API )
    os << indent << "Patient Name:" << m_PatientName << std::endl;
    os << indent << "Patient ID:" << m_PatientID << std::endl;
    os << indent << "Patient Sex:" << m_PatientSex << std::endl;
    os << indent << "Patient Age:" << m_PatientAge << std::endl;
    os << indent << "Study ID:" << m_StudyID << std::endl;
    os << indent << "Patient DOB:" << m_PatientDOB << std::endl;
    os << indent << "Study Description:" << m_StudyDescription << std::endl;
    os << indent << "Body Part:" << m_BodyPart << std::endl;
    os << indent << "Number Of Series In Study:" << m_NumberOfSeriesInStudy << std::endl;
    os << indent << "Number Of Study Related Series:" << m_NumberOfStudyRelatedSeries << std::endl;
    os << indent << "Study Date:" << m_StudyDate << std::endl;
    os << indent << "Modality:" << m_Modality << std::endl;
    os << indent << "Manufacturer:" << m_Manufacturer << std::endl;
    os << indent << "Institution Name:" << m_Institution << std::endl;
    os << indent << "Model:" << m_Model << std::endl;
    os << indent << "Scan Options:" << m_ScanOptions << std::endl;
#endif
  }
} // end namespace itk
-------------- next part --------------
A non-text attachment was scrubbed...
Name: itkGDCMImageIO.h
Type: text/x-chdr
Size: 12405 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/community/attachments/20170310/aadf4f48/attachment-0001.h>
-------------- next part --------------
_____________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html

Kitware offers ITK Training Courses, for more information visit:
http://www.kitware.com/products/protraining.php

Please keep messages on-topic and check the ITK FAQ at:
http://www.itk.org/Wiki/ITK_FAQ

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/insight-users


More information about the Community mailing list