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 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
|
/*=========================================================================
*
* 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
//
// It is often valuable to be able to query the entries from the header of a
// DICOM file. This can be used for consistency checking, or simply for
// verifying that we have the correct dataset in our hands. This example
// illustrates how to read a DICOM file and then print out most of the DICOM
// header information. The binary fields of the DICOM header are skipped.
//
// \index{DICOM!Header}
// \index{DICOM!Tags}
// \index{DICOM!Printing Tags}
// \index{DICOM!Dictionary}
// \index{DICOM!GDCM}
// \index{GDCM!Dictionary}
//
// Software Guide : EndLatex
// Software Guide : BeginLatex
//
// The headers of the main classes involved in this example are specified
// below. They include the image file reader, the GDCMImageIO object, the
// MetaDataDictionary and its entry element, the MetaDataObject.
//
// \index{MetaDataDictionary!header}
// \index{MetaDataObject!header}
// \index{GDCMImageIO!header}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
#include "itkImageFileReader.h"
#include "itkGDCMImageIO.h"
#include "itkMetaDataObject.h"
// Software Guide : EndCodeSnippet
#include "gdcmGlobal.h"
// Software Guide : BeginLatex
// Software Guide : EndLatex
int main( int argc, char* argv[] )
{
if( argc < 2 )
{
std::cerr << "Usage: " << argv[0] << " DicomFile [user defined dict]" << std::endl;
return EXIT_FAILURE;
}
// Software Guide : BeginLatex
//
// We instantiate the type to be used for storing the image once it is read
// into memory.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef signed short PixelType;
const unsigned int Dimension = 2;
typedef itk::Image< PixelType, Dimension > ImageType;
// Software Guide : EndCodeSnippet
if( argc == 3 )
{
// Specify a path where XML dicts can be found (Part 3/4 & 6)
gdcm::Global::GetInstance().Prepend( itksys::SystemTools::GetFilenamePath(argv[2]).c_str() );
// Load them !
gdcm::Global::GetInstance().LoadResourcesFiles();
}
// Software Guide : BeginLatex
//
// Using the image type as a template parameter we instantiate the type of the
// image file reader and construct one instance of it.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::ImageFileReader< ImageType > ReaderType;
ReaderType::Pointer reader = ReaderType::New();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The GDCM image IO type is declared and used for constructing one image IO
// object.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::GDCMImageIO ImageIOType;
ImageIOType::Pointer dicomIO = ImageIOType::New();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// We pass to the reader the filename of the image to be read and connect the
// ImageIO object to it too.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
reader->SetFileName( argv[1] );
reader->SetImageIO( dicomIO );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The reading process is triggered with a call to the \code{Update()} method.
// This call should be placed inside a \code{try/catch} block because its
// execution may result in exceptions being thrown.
//
// Software Guide : EndLatex
try
{
// Software Guide : BeginCodeSnippet
reader->Update();
// Software Guide : EndCodeSnippet
}
catch (itk::ExceptionObject &ex)
{
std::cout << ex << std::endl;
return EXIT_FAILURE;
}
// Software Guide : BeginLatex
//
// Now that the image has been read, we obtain the MetaDataDictionary from
// the ImageIO object using the \code{GetMetaDataDictionary()} method.
//
// \index{MetaDataDictionary}
// \index{GetMetaDataDictionary()!ImageIOBase}
// \index{ImageIOBase!GetMetaDataDictionary()}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::MetaDataDictionary DictionaryType;
const DictionaryType & dictionary = dicomIO->GetMetaDataDictionary();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Since we are interested only in the DICOM tags that can be expressed in
// strings, we declare a MetaDataObject suitable for managing strings.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::MetaDataObject< std::string > MetaDataStringType;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// We instantiate the iterators that will make possible to walk through all the
// entries of the MetaDataDictionary.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
DictionaryType::ConstIterator itr = dictionary.Begin();
DictionaryType::ConstIterator end = dictionary.End();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// For each one of the entries in the dictionary, we check first if its element
// can be converted to a string, a \code{dynamic\_cast} is used for this purpose.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
while( itr != end )
{
itk::MetaDataObjectBase::Pointer entry = itr->second;
MetaDataStringType::Pointer entryvalue =
dynamic_cast<MetaDataStringType *>( entry.GetPointer() );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// For those entries that can be converted, we take their DICOM tag and pass
// it to the \code{GetLabelFromTag()} method of the GDCMImageIO class. This
// method checks the DICOM dictionary and returns the string label
// associated with the tag that we are providing in the \code{tagkey}
// variable. If the label is found, it is returned in \code{labelId}
// variable. The method itself returns false if the tagkey is not found in
// the dictionary. For example "$0010|0010$" in \code{tagkey} becomes
// "Patient's Name" in \code{labelId}.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
if( entryvalue )
{
std::string tagkey = itr->first;
std::string labelId;
bool found = itk::GDCMImageIO::GetLabelFromTag( tagkey, labelId );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The actual value of the dictionary entry is obtained as a string with the
// \code{GetMetaDataObjectValue()} method.
//
// \index{MetaDataObject!GetMetaDataObjectValue()}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
std::string tagvalue = entryvalue->GetMetaDataObjectValue();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// At this point we can print out an entry by concatenating the DICOM Name or
// label, the numeric tag and its actual value.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
if( found )
{
std::cout << "(" << tagkey << ") " << labelId;
std::cout << " = " << tagvalue.c_str() << std::endl;
}
// Software Guide : EndCodeSnippet
else
{
std::cout << "(" << tagkey << ") " << "Unknown";
std::cout << " = " << tagvalue.c_str() << std::endl;
}
}
// Software Guide : BeginLatex
//
// Finally we just close the loop that will walk through all the Dictionary
// entries.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
++itr;
}
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// It is also possible to read a specific tag. In that case the string of the
// entry can be used for querying the MetaDataDictionary.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
std::string entryId = "0010|0010";
DictionaryType::ConstIterator tagItr = dictionary.Find( entryId );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// If the entry is actually found in the Dictionary, then we can attempt to
// convert it to a string entry by using a \code{dynamic\_cast}.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
if( tagItr != end )
{
MetaDataStringType::ConstPointer entryvalue =
dynamic_cast<const MetaDataStringType *>(
tagItr->second.GetPointer() );
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// If the dynamic cast succeeds, then we can print out the values of the label,
// the tag and the actual value.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
if( entryvalue )
{
std::string tagvalue = entryvalue->GetMetaDataObjectValue();
std::cout << "Patient's Name (" << entryId << ") ";
std::cout << " is: " << tagvalue.c_str() << std::endl;
}
// Software Guide : EndCodeSnippet
}
// Software Guide : BeginLatex
//
// Another way to read a specific tag is to use the encapsulation above
// MetaDataDictionary. Note that this is stricly equivalent to the above
// code.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
std::string tagkey = "0008|1050";
std::string labelId;
if( itk::GDCMImageIO::GetLabelFromTag( tagkey, labelId ) )
{
std::string value;
std::cout << labelId << " (" << tagkey << "): ";
if( dicomIO->GetValueFromTag(tagkey, value) )
{
std::cout << value;
}
else
{
std::cout << "(No Value Found in File)";
}
std::cout << std::endl;
}
else
{
std::cerr << "Trying to access inexistant DICOM tag." << std::endl;
}
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// For a full description of the DICOM dictionary please look at the file.
//
// \code{Insight/Utilities/gdcm/Dicts/dicomV3.dic}
//
// Software Guide : EndLatex
// Software Guide : BeginLatex
//
// The following piece of code will print out the proper pixel type /
// component for instantiating an \doxygen{ImageFileReader} that can properly
// import the printed DICOM file.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
itk::ImageIOBase::IOPixelType pixelType
= reader->GetImageIO()->GetPixelType();
itk::ImageIOBase::IOComponentType componentType
= reader->GetImageIO()->GetComponentType();
std::cout << "PixelType: " << reader->GetImageIO()
->GetPixelTypeAsString(pixelType) << std::endl;
std::cout << "Component Type: " << reader->GetImageIO()
->GetComponentTypeAsString(componentType) << std::endl;
// Software Guide : EndCodeSnippet
return EXIT_SUCCESS;
}
|