Hi,<br><br>Since this is not shown in the ITK software guide,<br>I thought this code that I wrote based on <a href="http://www.paraview.org/Bug/view.php?id=6258&nbn=1">http://www.paraview.org/Bug/view.php?id=6258&nbn=1</a> , might help someone:<br>
It shows how to change a MetaDataDictionaryArray when dealing with changing header info in Dicom series.<br><br>Thanks,<br>John<br><br>#if defined(_MSC_VER)<br>#pragma warning ( disable : 4786 )<br>#endif<br><br>#ifdef __BORLANDC__<br>
#define ITK_LEAN_AND_MEAN<br>#endif<br><br>//<br>// This example illustrates how to change a MetaDataDictionaryArray.<br>// This example illustrates how to read two DICOM series, adds key <br>// tags that are in the second DICOM series to the first DICOM series<br>
// and write it back with some changed header information as another <br>// DICOM series. This can be useful when sometimes conversion between<br>// different file formats as between NIFTI and DICOM and some dicom tags <br>
// are lost.<br>// The keys are defined in the file<br>//<br>// \code{Insight/Utilities/gdcm/Dicts/dicomV3.dic}<br>// <br>// Please note that modifying the content of a DICOM header is a very risky<br>// operation. The Header contains fundamental information about the patient<br>
// and therefore its consistency must be protected from any data corruption.<br>// Before attempting to modify the DICOM headers of your files, you must make<br>// sure that you have a very good reason for doing so, and that you can ensure<br>
// that this information change will not result in a lower quality of health<br>// care to be delivered to the patient.<br>//<br>// \index{DICOM!Changing Headers}<br>//<br><br>// Software Guide : BeginLatex<br>// <br>// We must start by including the relevant header files. Here we include the<br>
// image reader, image writer, the image, the Meta data dictionary and its<br>// entries the Meta data objects and the GDCMImageIO. The Meta data dictionary<br>// is the data container that stores all the entries from the DICOM header once<br>
// the DICOM image file is read into an ITK image.<br>//<br>// Software Guide : EndLatex<br><br>// Software Guide : BeginCodeSnippet<br>#include "itkImageFileReader.h"<br>#include "itkImageFileWriter.h"<br>
#include "itkImage.h"<br>#include "itkMetaDataDictionary.h"<br>#include "itkMetaDataObject.h"<br>#include "itkGDCMImageIO.h"<br>// Software Guide : EndCodeSnippet<br><br>#include <list><br>
#include <fstream><br><br><br>#include "itkGDCMImageIO.h"<br>#include "itkGDCMSeriesFileNames.h"<br>#include "itkImageSeriesReader.h"<br>#include "itkImageSeriesWriter.h"<br><br>
<br>int main(int argc, char* argv[])<br>{<br><br> if( argc < 4 )<br> {<br> std::cerr << "Usage: " << argv[0] << " OriginalDicomImageDIR ProcessedDicomImageDIR OutputDicomImageDIR\n";<br>
//DIR means Directory<br><br><br> return EXIT_FAILURE;<br> }<br> <br> typedef unsigned short InputPixelType;<br><br> <br> const unsigned int Dimension = 3;<br><br> typedef itk::Image< InputPixelType, Dimension > InputImageType;<br>
<br> typedef itk::GDCMSeriesFileNames NamesGeneratorTypeOrig;<br> NamesGeneratorTypeOrig::Pointer namesGeneratororig = NamesGeneratorTypeOrig::New();<br><br> namesGeneratororig->SetInputDirectory( argv[1] );<br>
<br> typedef itk::Image< InputPixelType, Dimension > ImageTypeOrig;<br> typedef itk::ImageSeriesReader< ImageTypeOrig > ReaderTypeOrig;<br><br> const ReaderTypeOrig::FileNamesContainer & filenamesorig = <br>
namesGeneratororig->GetInputFileNames();<br><br> unsigned int numberOfFilenames = filenamesorig.size();<br> std::cout << numberOfFilenames << std::endl; <br> for(unsigned int fni = 0; fni<numberOfFilenames; fni++)<br>
{<br> std::cout << "filename # " << fni << " = ";<br> std::cout << filenamesorig[fni] << std::endl;<br> }<br><br> typedef itk::GDCMImageIO ImageIOTypeOrig;<br>
ImageIOTypeOrig::Pointer gdcmImageIOorig = ImageIOTypeOrig::New();<br> //reader->SetImageIO( gdcmImageIOorig );<br><br> ReaderTypeOrig::Pointer readerorig = ReaderTypeOrig::New();<br><br> readerorig->SetImageIO( gdcmImageIOorig );<br>
readerorig->SetFileNames( filenamesorig );<br><br> //end of added code<br><br>// Software Guide : BeginLatex<br>// <br>// The reading of the image is triggered by invoking \code{Update()} in the<br>// reader.<br>//<br>
// Software Guide : EndLatex<br><br><br> try<br> {<br>// Software Guide : BeginCodeSnippet<br> readerorig->Update();<br>// Software Guide : EndCodeSnippet<br> }<br> catch (itk::ExceptionObject & e)<br> {<br>
std::cerr << "exception in file reader " << std::endl;<br> std::cerr << e.GetDescription() << std::endl;<br> std::cerr << e.GetLocation() << std::endl;<br> return EXIT_FAILURE;<br>
}<br><br> typedef itk::Image< InputPixelType, Dimension > InputImageType2;<br><br> typedef itk::GDCMSeriesFileNames NamesGeneratorTypeProc;<br> NamesGeneratorTypeProc::Pointer namesGeneratorproc = NamesGeneratorTypeProc::New();<br>
<br> namesGeneratorproc->SetInputDirectory( argv[2] );<br><br> typedef itk::Image< InputPixelType, Dimension > ImageTypeProc;<br> typedef itk::ImageSeriesReader< ImageTypeProc > ReaderTypeProc;<br>
<br> const ReaderTypeProc::FileNamesContainer & filenamesproc = <br> namesGeneratorproc->GetInputFileNames();<br> <br> numberOfFilenames = filenamesproc.size();<br> std::cout << numberOfFilenames << std::endl; <br>
for(unsigned int fni = 0; fni<numberOfFilenames; fni++)<br> {<br> std::cout << "filename # " << fni << " = ";<br> std::cout << filenamesproc[fni] << std::endl;<br>
}<br><br> typedef itk::GDCMImageIO ImageIOTypeProc;<br> ImageIOTypeProc::Pointer gdcmImageIOproc = ImageIOTypeProc::New();<br><br> ReaderTypeProc::Pointer readerproc = ReaderTypeProc::New();<br><br> readerproc->SetImageIO( gdcmImageIOproc );<br>
readerproc->SetFileNames( filenamesproc );<br><br> try<br> {<br> readerproc->Update();<br> }<br> catch (itk::ExceptionObject & e)<br> {<br> std::cerr << "exception in file reader " << std::endl;<br>
std::cerr << e.GetDescription() << std::endl;<br> std::cerr << e.GetLocation() << std::endl;<br> return EXIT_FAILURE;<br> }<br><br> typedef itk::MetaDataObject< std::string > MetaDataStringType;<br>
<br> typedef itk::MetaDataDictionary DictionaryType1b;<br> typedef itk::MetaDataDictionary DictionaryType2b;<br> <br> std::vector<DictionaryType2b*> pdictArray2b;<br><br> DictionaryType1b::ConstIterator itr1b;<br>
DictionaryType1b::ConstIterator end1b;<br><br> DictionaryType2b::ConstIterator itr2b;<br> DictionaryType2b::ConstIterator end2b;<br> <br> for ( unsigned int idx = 0;<br> idx < readerproc->GetMetaDataDictionaryArray()->size();<br>
idx++ )<br> {<br><br> itk::MetaDataDictionary* pdictionary1b = new itk::MetaDataDictionary;<br> itk::MetaDataDictionary* pSrc1b = (*(readerorig->GetMetaDataDictionaryArray()))[idx];<br>
<br> itk::MetaDataDictionary* pdictionary2b = new itk::MetaDataDictionary;<br> itk::MetaDataDictionary* pSrc2b = (*(readerproc->GetMetaDataDictionaryArray()))[idx];<br><br> if ( pSrc2b )<br>
{<br> *pdictionary1b = (*pSrc1b);<br> *pdictionary2b = (*pSrc2b);<br><br><br> itr1b = pdictionary1b->Begin();<br> end1b = pdictionary1b->End();<br><br> itr2b = pdictionary2b->Begin();<br>
end2b = pdictionary2b->End();<br> <br> while( itr1b != end1b )<br> {<br> itk::MetaDataObjectBase::Pointer entry1b = itr1b->second;<br><br> MetaDataStringType::Pointer entryvalue1b = <br>
dynamic_cast<MetaDataStringType *>( entry1b.GetPointer() );<br><br> std::string tagkey1b = itr1b->first;<br><br> <br> DictionaryType2b::ConstIterator tagItr2b = pdictionary2b->Find( tagkey1b );<br>
<br> if( tagItr2b == end2b )<br> {<br> std::string tagkey = itr1b->first;<br> std::string tagvalue = entryvalue1b->GetMetaDataObjectValue();<br> //std::cout << tagkey << " = " << tagvalue << std::endl;<br>
itk::EncapsulateMetaData<std::string>( *pdictionary2b, tagkey , tagvalue ); <br> }<br> <br> ++itr1b;<br> }<br> <br> <br> std::string entryIdMR = "0008|0060";<br>
std::string valueMR = "MR";<br> itk::EncapsulateMetaData<std::string>( *pdictionary2b, entryIdMR, valueMR );<br><br> <br> pdictArray2b.push_back( pdictionary2b );<br>
<br> }<br> }<br><br> typedef unsigned short OutputPixelType;<br> const unsigned int OutputDimension = 2;<br><br> typedef itk::Image< OutputPixelType, OutputDimension > Image2DType;<br>
<br> typedef itk::ImageSeriesWriter< <br> ImageTypeProc, Image2DType > SeriesWriterType;<br><br> SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();<br><br> seriesWriter->SetMetaDataDictionaryArray( &pdictArray2b );<br>
<br> seriesWriter->SetInput( readerproc->GetOutput() );<br> seriesWriter->SetImageIO( gdcmImageIOproc );<br><br> namesGeneratorproc->SetOutputDirectory( argv[3] );<br><br> seriesWriter->SetFileNames( namesGeneratorproc->GetOutputFileNames() );<br>
<br> try<br> {<br> seriesWriter->Update();<br> }<br> catch (itk::ExceptionObject & e)<br> {<br> std::cerr << "exception in file writer " << std::endl;<br> std::cerr << e.GetDescription() << std::endl;<br>
std::cerr << e.GetLocation() << std::endl;<br> return EXIT_FAILURE;<br> }<br><br> // Software Guide : BeginLatex<br> // <br> // Remember again, that modifying the header entries of a DICOM file involves<br>
// very serious risks for patients and therefore must be done with extreme<br> // caution.<br> //<br> // Software Guide : EndLatex<br><br><br> return EXIT_SUCCESS;<br><br>}<br><br><br>Thanks,<br>John<br>