1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
/*=========================================================================
*
* 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.
*
*=========================================================================*/
// Software Guide : BeginLatex
//
// This example illustrates how to read a single DICOM slice and write it back
// with some changed header information as another DICOM slice. Header
// Key/Value pairs can be specified on the command line. 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 being delivered to the patient.
//
// \index{DICOM!Changing Headers}
//
// Software Guide : EndLatex
// Software Guide : BeginLatex
//
// We must start by including the relevant header files. Here we include the
// image reader, image writer, the image, the metadata dictionary and its
// entries, the metadata objects and the GDCMImageIO. The metadata 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 "itkMetaDataObject.h"
#include "itkGDCMImageIO.h"
// Software Guide : EndCodeSnippet
#include <list>
#include <fstream>
int main(int argc, char* argv[])
{
if( argc < 5 )
{
std::cerr << "Usage: " << argv[0] << " DicomImage OutputDicomImage Entry Value\n";
return EXIT_FAILURE;
}
// Software Guide : BeginLatex
//
// We declare the image type by selecting a particular pixel type and image
// dimension.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef signed short InputPixelType;
const unsigned int Dimension = 2;
typedef itk::Image< InputPixelType, Dimension > InputImageType;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// We instantiate the reader type by using the image type as template
// parameter. An instance of the reader is created and the file name to be read
// is taken from the command line arguments.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::ImageFileReader< InputImageType > ReaderType;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName( argv[1] );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The GDCMImageIO object is created in order to provide the services for
// reading and writing DICOM files. The newly created image IO class is
// connected to the reader.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::GDCMImageIO ImageIOType;
ImageIOType::Pointer gdcmImageIO = ImageIOType::New();
reader->SetImageIO( gdcmImageIO );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The reading of the image is triggered by invoking \code{Update()} in the
// reader.
//
// Software Guide : EndLatex
try
{
// Software Guide : BeginCodeSnippet
reader->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;
}
// Software Guide : BeginLatex
//
// We take the metadata dictionary from the image that the reader had loaded
// in memory.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
InputImageType::Pointer inputImage = reader->GetOutput();
typedef itk::MetaDataDictionary DictionaryType;
DictionaryType & dictionary = inputImage->GetMetaDataDictionary();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Now we access the entries in the metadata dictionary, and for particular
// key values we assign a new content to the entry. This is done here by taking
// \{key,value\} pairs from the command line arguments. The relevant method is
// \code{EncapsulateMetaData} that takes the dictionary and for a given key
// provided by \code{entryId}, replaces the current value with the content of
// the \code{value} variable. This is repeated for every potential pair present
// in the command line arguments.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
for (int i = 3; i < argc; i+=2)
{
std::string entryId( argv[i] );
std::string value( argv[i+1] );
itk::EncapsulateMetaData<std::string>( dictionary, entryId, value );
}
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Now that the dictionary has been updated, we proceed to save the image. This
// output image will have the modified data associated with its DICOM header.
//
// Using the image type, we instantiate a writer type and construct a writer.
// A short pipeline between the reader and the writer is connected. The
// filename to write is taken from the command line arguments. The image IO
// object is connected to the writer.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::ImageFileWriter< InputImageType > Writer1Type;
Writer1Type::Pointer writer1 = Writer1Type::New();
writer1->SetInput( reader->GetOutput() );
writer1->SetFileName( argv[2] );
writer1->SetImageIO( gdcmImageIO );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Execution of the writer is triggered by invoking the \code{Update()} method.
//
// Software Guide : EndLatex
try
{
// Software Guide : BeginCodeSnippet
writer1->Update();
// Software Guide : EndCodeSnippet
}
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;
}
|