[Insight-users] I thought this code might help someone; it shows how to change a MetaDataDictionaryArray when dealing with changing header info in Dicom series.

John Drozd john.drozd at gmail.com
Thu Oct 28 20:09:49 EDT 2010


Hi,

Since this is not shown in the ITK software guide,
I thought this code that I wrote based on
http://www.paraview.org/Bug/view.php?id=6258&nbn=1 ,  might help someone:
It shows how to change a MetaDataDictionaryArray when dealing with changing
header info in Dicom series.

Thanks,
John

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//
//  This example illustrates how to change a MetaDataDictionaryArray.
//  This example illustrates how to read two DICOM series, adds key
//  tags that are in the second DICOM series to the first DICOM series
//  and write it back with some changed header information as another
//  DICOM series.  This can be useful when sometimes conversion between
//  different file formats as between NIFTI and DICOM and some dicom tags
//  are lost.
//  The keys are defined in the file
//
//  \code{Insight/Utilities/gdcm/Dicts/dicomV3.dic}
//
//  Please note that modifying the content of a DICOM header is a very risky
//  operation. The Header contains fundamental information about the patient
//  and therefore its consistency must be protected from any data
corruption.
//  Before attempting to modify the DICOM headers of your files, you must
make
//  sure that you have a very good reason for doing so, and that you can
ensure
//  that this information change will not result in a lower quality of
health
//  care to be delivered to the patient.
//
//  \index{DICOM!Changing Headers}
//

// Software Guide : BeginLatex
//
// We must start by including the relevant header files. Here we include the
// image reader, image writer, the image, the Meta data dictionary and its
// entries the Meta data objects and the GDCMImageIO. The Meta data
dictionary
// is the data container that stores all the entries from the DICOM header
once
// the DICOM image file is read into an ITK image.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImage.h"
#include "itkMetaDataDictionary.h"
#include "itkMetaDataObject.h"
#include "itkGDCMImageIO.h"
// Software Guide : EndCodeSnippet

#include <list>
#include <fstream>


#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkImageSeriesReader.h"
#include "itkImageSeriesWriter.h"


int main(int argc, char* argv[])
{

  if( argc < 4 )
    {
      std::cerr << "Usage: " << argv[0] << " OriginalDicomImageDIR
ProcessedDicomImageDIR OutputDicomImageDIR\n";
      //DIR means Directory


    return EXIT_FAILURE;
    }

  typedef unsigned short InputPixelType;


  const unsigned int   Dimension = 3;

  typedef itk::Image< InputPixelType, Dimension > InputImageType;

  typedef itk::GDCMSeriesFileNames                NamesGeneratorTypeOrig;
  NamesGeneratorTypeOrig::Pointer namesGeneratororig =
NamesGeneratorTypeOrig::New();

  namesGeneratororig->SetInputDirectory( argv[1] );

  typedef itk::Image< InputPixelType, Dimension >      ImageTypeOrig;
  typedef itk::ImageSeriesReader< ImageTypeOrig >     ReaderTypeOrig;

  const ReaderTypeOrig::FileNamesContainer & filenamesorig =
                            namesGeneratororig->GetInputFileNames();

  unsigned int numberOfFilenames =  filenamesorig.size();
  std::cout << numberOfFilenames << std::endl;
  for(unsigned int fni = 0; fni<numberOfFilenames; fni++)
    {
    std::cout << "filename # " << fni << " = ";
    std::cout << filenamesorig[fni] << std::endl;
    }

  typedef itk::GDCMImageIO           ImageIOTypeOrig;
  ImageIOTypeOrig::Pointer gdcmImageIOorig = ImageIOTypeOrig::New();
  //reader->SetImageIO( gdcmImageIOorig );

  ReaderTypeOrig::Pointer readerorig = ReaderTypeOrig::New();

  readerorig->SetImageIO( gdcmImageIOorig );
  readerorig->SetFileNames( filenamesorig );

  //end of added code

// Software Guide : BeginLatex
//
// The reading of the image is triggered by invoking \code{Update()} in the
// reader.
//
// Software Guide : EndLatex


  try
    {
// Software Guide : BeginCodeSnippet
    readerorig->Update();
// Software Guide : EndCodeSnippet
    }
  catch (itk::ExceptionObject & e)
    {
    std::cerr << "exception in file reader " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;
    }

  typedef itk::Image< InputPixelType, Dimension > InputImageType2;

  typedef itk::GDCMSeriesFileNames                NamesGeneratorTypeProc;
  NamesGeneratorTypeProc::Pointer namesGeneratorproc =
NamesGeneratorTypeProc::New();

  namesGeneratorproc->SetInputDirectory( argv[2] );

  typedef itk::Image< InputPixelType, Dimension >      ImageTypeProc;
  typedef itk::ImageSeriesReader< ImageTypeProc >     ReaderTypeProc;

  const ReaderTypeProc::FileNamesContainer & filenamesproc =
                            namesGeneratorproc->GetInputFileNames();

  numberOfFilenames =  filenamesproc.size();
  std::cout << numberOfFilenames << std::endl;
  for(unsigned int fni = 0; fni<numberOfFilenames; fni++)
    {
    std::cout << "filename # " << fni << " = ";
    std::cout << filenamesproc[fni] << std::endl;
    }

  typedef itk::GDCMImageIO           ImageIOTypeProc;
  ImageIOTypeProc::Pointer gdcmImageIOproc = ImageIOTypeProc::New();

  ReaderTypeProc::Pointer readerproc = ReaderTypeProc::New();

  readerproc->SetImageIO( gdcmImageIOproc );
  readerproc->SetFileNames( filenamesproc );

  try
    {
    readerproc->Update();
    }
  catch (itk::ExceptionObject & e)
    {
    std::cerr << "exception in file reader " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;
    }

  typedef itk::MetaDataObject< std::string > MetaDataStringType;

  typedef itk::MetaDataDictionary   DictionaryType1b;
  typedef itk::MetaDataDictionary   DictionaryType2b;

  std::vector<DictionaryType2b*>         pdictArray2b;

  DictionaryType1b::ConstIterator itr1b;
  DictionaryType1b::ConstIterator end1b;

  DictionaryType2b::ConstIterator itr2b;
  DictionaryType2b::ConstIterator end2b;

  for ( unsigned int idx = 0;
                  idx < readerproc->GetMetaDataDictionaryArray()->size();
                  idx++ )
            {

                itk::MetaDataDictionary* pdictionary1b = new
itk::MetaDataDictionary;
                itk::MetaDataDictionary* pSrc1b =
(*(readerorig->GetMetaDataDictionaryArray()))[idx];

        itk::MetaDataDictionary* pdictionary2b = new
itk::MetaDataDictionary;
                itk::MetaDataDictionary* pSrc2b =
(*(readerproc->GetMetaDataDictionaryArray()))[idx];

                if ( pSrc2b )
                {
          *pdictionary1b = (*pSrc1b);
          *pdictionary2b = (*pSrc2b);


          itr1b = pdictionary1b->Begin();
          end1b = pdictionary1b->End();

          itr2b = pdictionary2b->Begin();
          end2b = pdictionary2b->End();

          while( itr1b != end1b )
            {
              itk::MetaDataObjectBase::Pointer  entry1b = itr1b->second;

              MetaDataStringType::Pointer entryvalue1b =
            dynamic_cast<MetaDataStringType *>( entry1b.GetPointer() );

              std::string tagkey1b   = itr1b->first;


              DictionaryType2b::ConstIterator tagItr2b =
pdictionary2b->Find( tagkey1b );

              if( tagItr2b == end2b )
            {
              std::string tagkey   = itr1b->first;
              std::string tagvalue = entryvalue1b->GetMetaDataObjectValue();
              //std::cout << tagkey <<  " = " << tagvalue << std::endl;
              itk::EncapsulateMetaData<std::string>( *pdictionary2b, tagkey
, tagvalue );
            }

              ++itr1b;
            }


          std::string entryIdMR = "0008|0060";
          std::string valueMR = "MR";
          itk::EncapsulateMetaData<std::string>( *pdictionary2b, entryIdMR,
valueMR );


          pdictArray2b.push_back( pdictionary2b );

                }
            }

  typedef unsigned short    OutputPixelType;
  const unsigned int      OutputDimension = 2;

  typedef itk::Image< OutputPixelType, OutputDimension >    Image2DType;

  typedef itk::ImageSeriesWriter<
  ImageTypeProc, Image2DType >  SeriesWriterType;

  SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();

  seriesWriter->SetMetaDataDictionaryArray( &pdictArray2b );

  seriesWriter->SetInput( readerproc->GetOutput() );
  seriesWriter->SetImageIO( gdcmImageIOproc );

  namesGeneratorproc->SetOutputDirectory( argv[3] );

  seriesWriter->SetFileNames( namesGeneratorproc->GetOutputFileNames() );

  try
    {
    seriesWriter->Update();
    }
  catch (itk::ExceptionObject & e)
    {
    std::cerr << "exception in file writer " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;
    }

  // Software Guide : BeginLatex
  //
  // Remember again, that modifying the header entries of a DICOM file
involves
  // very serious risks for patients and therefore must be done with extreme
  // caution.
  //
  // Software Guide : EndLatex


  return EXIT_SUCCESS;

}


Thanks,
John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.itk.org/pipermail/insight-users/attachments/20101028/3bd14dbb/attachment.htm>


More information about the Insight-users mailing list