vtkDICOMImageReader.cxx 16.5 KB
Newer Older
Matt Turek's avatar
Matt Turek committed
1
2
3
4
5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkDICOMImageReader.cxx

Mathieu Malaterre's avatar
Mathieu Malaterre committed
6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
Matt Turek's avatar
Matt Turek committed
7
8
9
10
11
12
13
14
15
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkDICOMImageReader.h"
16
17
18

#include "vtkDirectory.h"
#include "vtkDataArray.h"
Matt Turek's avatar
Matt Turek committed
19
20
21
22
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"

23
24
#include <vtkstd/vector>
#include <vtkstd/string>
Matt Turek's avatar
Matt Turek committed
25

26
27
#include <sys/stat.h>

28
29
30
31
#include "DICOMAppHelper.h"
#include "DICOMParser.h"

vtkCxxRevisionMacro(vtkDICOMImageReader, "1.32.6.1");
Matt Turek's avatar
Matt Turek committed
32
33
vtkStandardNewMacro(vtkDICOMImageReader);

34
class vtkDICOMImageReaderVector : public vtkstd::vector<vtkstd::string>
Matt Turek's avatar
Matt Turek committed
35
36
37
38
{

};

39
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
40
41
42
43
44
vtkDICOMImageReader::vtkDICOMImageReader()
{
  this->Parser = new DICOMParser();
  this->AppHelper = new DICOMAppHelper();
  this->DirectoryName = NULL;
45
46
47
48
  this->PatientName = NULL;
  this->StudyUID = NULL;
  this->StudyID = NULL;
  this->TransferSyntaxUID = NULL;
49
  this->DICOMFileNames = new vtkDICOMImageReaderVector();
Matt Turek's avatar
Matt Turek committed
50
51
}

52
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
53
54
55
56
57
vtkDICOMImageReader::~vtkDICOMImageReader()
{
  delete this->Parser;
  delete this->AppHelper;
  delete this->DICOMFileNames;
Ken Martin's avatar
Ken Martin committed
58

59
60
61
  if (this->DirectoryName)
    {
    delete [] this->DirectoryName;
Ken Martin's avatar
Ken Martin committed
62
    }
63
64
65
  if (this->PatientName)
    {
    delete [] this->PatientName;
66
    }
67
68
69
  if (this->StudyUID)
    {
    delete [] this->StudyUID;
70
    }
71
72
73
  if (this->StudyID)
    {
    delete [] this->StudyID;
74
    }
75
76
77
  if (this->TransferSyntaxUID)
    {
    delete [] this->TransferSyntaxUID;
78
    }
Matt Turek's avatar
Matt Turek committed
79
80
}

81
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
82
83
void vtkDICOMImageReader::PrintSelf(ostream& os, vtkIndent indent)
{
84
  this->Superclass::PrintSelf(os, indent);
Matt Turek's avatar
Matt Turek committed
85
86
  if (this->DirectoryName)
    {
Matt Turek's avatar
Matt Turek committed
87
    os << "DirectoryName : " << this->DirectoryName << "\n";
Matt Turek's avatar
Matt Turek committed
88
89
90
    }
  else
    {
Matt Turek's avatar
Matt Turek committed
91
    os << "DirectoryName : (NULL)" << "\n";
Matt Turek's avatar
Matt Turek committed
92
93
94
    }
  if (this->FileName)
    {
Matt Turek's avatar
Matt Turek committed
95
    os << "FileName : " << this->FileName << "\n";
Matt Turek's avatar
Matt Turek committed
96
97
98
    }
  else
    {
Matt Turek's avatar
Matt Turek committed
99
    os << "FileName : (NULL)" << "\n";
Matt Turek's avatar
Matt Turek committed
100
101
    }

Matt Turek's avatar
Matt Turek committed
102
103
}

104
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
105
106
107
int vtkDICOMImageReader::CanReadFile(const char* fname)
{
  bool canOpen = this->Parser->OpenFile((char*) fname);
108
  if (!canOpen)
Matt Turek's avatar
Matt Turek committed
109
110
111
112
113
    {
    vtkErrorMacro("DICOMParser couldn't open : " << fname);
    return 0;
    }
  bool canRead = this->Parser->IsDICOMFile();
114
  if (canRead)
Matt Turek's avatar
Matt Turek committed
115
116
117
118
119
    {
    return 1;
    }
  else
    {
120
    vtkErrorMacro("DICOMParser couldn't parse : " << fname);
Matt Turek's avatar
Matt Turek committed
121
122
123
124
    return 0;
    }
}

125
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
126
127
128
129
130
131
132
133
134
void vtkDICOMImageReader::ExecuteInformation()
{
  if (this->FileName == NULL && this->DirectoryName == NULL)
    {
    return;
    }

  if (this->FileName)
    {
135
136
137
138
139
140
141
    struct stat fs;
    if ( stat(this->FileName, &fs) )
      {
      vtkErrorMacro("Unable to open file " << this->FileName );
      return;
      }

Matt Turek's avatar
Matt Turek committed
142
    this->DICOMFileNames->clear();
Matt Turek's avatar
Matt Turek committed
143
    this->AppHelper->Clear();
Matt Turek's avatar
Matt Turek committed
144
    this->Parser->ClearAllDICOMTagCallbacks();
145

Matt Turek's avatar
Matt Turek committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
    this->Parser->OpenFile(this->FileName);
    this->AppHelper->RegisterCallbacks(this->Parser);

    this->Parser->ReadHeader();
    this->SetupOutputInformation(1);
    }
  else if (this->DirectoryName)
    {
    vtkDirectory* dir = vtkDirectory::New();
    int opened = dir->Open(this->DirectoryName);
    if (!opened)
      {
      vtkErrorMacro("Couldn't open " << this->DirectoryName);
      dir->Delete();
      return;
      }
    int numFiles = dir->GetNumberOfFiles();

    vtkDebugMacro( << "There are " << numFiles << " files in the directory.");

    this->DICOMFileNames->clear();
Matt Turek's avatar
Matt Turek committed
167
    this->AppHelper->Clear();
Matt Turek's avatar
Matt Turek committed
168
169
170
171
172
173
174
175
176

    for (int i = 0; i < numFiles; i++)
      {
      if (strcmp(dir->GetFile(i), ".") == 0 ||
          strcmp(dir->GetFile(i), "..") == 0)
        {
        continue;
        }

Ken Martin's avatar
Ken Martin committed
177
178
179
      vtkstd::string fileString = this->DirectoryName;
      fileString += "/";
      fileString += dir->GetFile(i);
Matt Turek's avatar
Matt Turek committed
180
181
182
183
184
185
186
187
188
189
190
191
192
193

      int val = this->CanReadFile(fileString.c_str());

      if (val == 1)
        {
        vtkDebugMacro( << "Adding " << fileString.c_str() << " to DICOMFileNames.");
        this->DICOMFileNames->push_back(fileString);
        }
      else
        {
        vtkDebugMacro( << fileString.c_str() << " - DICOMParser CanReadFile returned : " << val);
        }

      }
194
    vtkstd::vector<vtkstd::string>::iterator iter;
195

Matt Turek's avatar
Matt Turek committed
196
197
198
199
200
201
    for (iter = this->DICOMFileNames->begin();
         iter != this->DICOMFileNames->end();
         iter++)
      {
      char* fn = (char*) (*iter).c_str();
      vtkDebugMacro( << "Trying : " << fn);
202

Matt Turek's avatar
Matt Turek committed
203
204
205
206
207
208
209
      bool couldOpen = this->Parser->OpenFile(fn);
      if (!couldOpen)
        {
        dir->Delete();
        return;
        }

210
      //
Matt Turek's avatar
Matt Turek committed
211
212
213
214
215
216
217
218
      this->Parser->ClearAllDICOMTagCallbacks();
      this->AppHelper->RegisterCallbacks(this->Parser);

      this->Parser->ReadHeader();

      vtkDebugMacro( << "File name : " << fn );
      vtkDebugMacro( << "Slice number : " << this->AppHelper->GetSliceNumber());
      }
219

Matt Turek's avatar
Matt Turek committed
220
    vtkstd::vector<vtkstd::pair<float, vtkstd::string> > sortedFiles;
221

Jim Miller's avatar
Jim Miller committed
222
    this->AppHelper->GetImagePositionPatientFilenamePairs(sortedFiles, false);
Matt Turek's avatar
Matt Turek committed
223
    this->SetupOutputInformation(static_cast<int>(sortedFiles.size()));
Matt Turek's avatar
Matt Turek committed
224
225
226
227
228
229

    //this->AppHelper->OutputSeries();

    if (sortedFiles.size() > 0)
      {
      this->DICOMFileNames->clear();
Matt Turek's avatar
Matt Turek committed
230
      vtkstd::vector<vtkstd::pair<float, vtkstd::string> >::iterator siter;
Matt Turek's avatar
Matt Turek committed
231
      for (siter = sortedFiles.begin();
232
233
234
235
236
237
238
           siter != sortedFiles.end();
           siter++)
        {
        vtkDebugMacro(<< "Sorted filename : " << (*siter).second.c_str());
        vtkDebugMacro(<< "Adding file " << (*siter).second.c_str() << " at slice : " << (*siter).first);
        this->DICOMFileNames->push_back((*siter).second);
        }
Matt Turek's avatar
Matt Turek committed
239
240
241
242
243
244
245
      }
    else
      {
      vtkErrorMacro( << "Couldn't get sorted files. Slices may be in wrong order!");
      }
    dir->Delete();
    }
246

Matt Turek's avatar
Matt Turek committed
247
248
}

249
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
250
251
252
void vtkDICOMImageReader::ExecuteData(vtkDataObject *output)
{
  vtkImageData *data = this->AllocateOutputData(output);
253
254
255
256
257
258
259

  if (!this->FileName && this->DICOMFileNames->size() == 0)
    {
    vtkErrorMacro( << "Either a filename was not specified or the specified directory does not contain any DICOM images.");
    return;
    }

Matt Turek's avatar
Matt Turek committed
260
261
  data->GetPointData()->GetScalars()->SetName("DICOMImage");

262
263
  this->ComputeDataIncrements();

Matt Turek's avatar
Matt Turek committed
264
265
266
267
268
  if (this->FileName)
    {
    vtkDebugMacro( << "Single file : " << this->FileName);
    this->Parser->ClearAllDICOMTagCallbacks();
    this->Parser->OpenFile(this->FileName);
Matt Turek's avatar
Matt Turek committed
269
    this->AppHelper->Clear();
Matt Turek's avatar
Matt Turek committed
270
    this->AppHelper->RegisterCallbacks(this->Parser);
Matt Turek's avatar
Matt Turek committed
271
    this->AppHelper->RegisterPixelDataCallback(this->Parser);
Matt Turek's avatar
Matt Turek committed
272
273
274
275
276
277
278
279
280
281

    this->Parser->ReadHeader();

    void* imgData = NULL;
    DICOMParser::VRTypes dataType;
    unsigned long imageDataLength;

    this->AppHelper->GetImageData(imgData, dataType, imageDataLength);

    void* buffer = data->GetScalarPointer();
282
283
284
285
286
    if (buffer == NULL)
      {
      vtkErrorMacro(<< "No memory allocated for image data!");
      return;
      }
287
288
289
    // DICOM stores the upper left pixel as the first pixel in an
    // image. VTK stores the lower left pixel as the first pixel in
    // an image.  Need to flip the data.
290
    vtkIdType rowLength;
291
292
293
294
295
296
297
298
299
300
    rowLength = this->DataIncrements[1];
    unsigned char *b = (unsigned char *)buffer;
    unsigned char *iData = (unsigned char *)imgData;
    iData += (imageDataLength - rowLength); // beginning of last row
    for (int i=0; i < this->AppHelper->GetHeight(); ++i)
      {
      memcpy(b, iData, rowLength);
      b += rowLength;
      iData -= rowLength;
      }
Matt Turek's avatar
Matt Turek committed
301
302
303
    }
  else if (this->DICOMFileNames->size() > 0)
    {
Matt Turek's avatar
Matt Turek committed
304
    vtkDebugMacro( << "Multiple files (" << static_cast<int>(this->DICOMFileNames->size()) << ")");
Matt Turek's avatar
Matt Turek committed
305
    this->Parser->ClearAllDICOMTagCallbacks();
Matt Turek's avatar
Matt Turek committed
306
    this->AppHelper->Clear();
Matt Turek's avatar
Matt Turek committed
307
    this->AppHelper->RegisterCallbacks(this->Parser);
Matt Turek's avatar
Matt Turek committed
308
    this->AppHelper->RegisterPixelDataCallback(this->Parser);
Matt Turek's avatar
Matt Turek committed
309
310

    void* buffer = data->GetScalarPointer();
311
312
313
314
315
    if (buffer == NULL)
      {
      vtkErrorMacro(<< "No memory allocated for image data!");
      return;
      }
316
317

    vtkstd::vector<vtkstd::string>::iterator fiter;
Matt Turek's avatar
Matt Turek committed
318
319

    int count = 0;
Matt Turek's avatar
Matt Turek committed
320
    int numFiles = static_cast<int>(this->DICOMFileNames->size());
Matt Turek's avatar
Matt Turek committed
321
322
323
324

    for (fiter = this->DICOMFileNames->begin();
         fiter != this->DICOMFileNames->end();
         fiter++)
325
326
327
328
329
      {
      count++;
      vtkDebugMacro( << "File : " << (*fiter).c_str());
      this->Parser->OpenFile((char*)(*fiter).c_str());
      this->Parser->ReadHeader();
Matt Turek's avatar
Matt Turek committed
330

331
332
333
      void* imgData = NULL;
      DICOMParser::VRTypes dataType;
      unsigned long imageDataLengthInBytes;
Matt Turek's avatar
Matt Turek committed
334

335
      this->AppHelper->GetImageData(imgData, dataType, imageDataLengthInBytes);
Matt Turek's avatar
Matt Turek committed
336

337
338
339
      // DICOM stores the upper left pixel as the first pixel in an
      // image. VTK stores the lower left pixel as the first pixel in
      // an image.  Need to flip the data.
340
      vtkIdType rowLength;
341
342
343
344
345
346
347
348
349
350
      rowLength = this->DataIncrements[1];
      unsigned char *b = (unsigned char *)buffer;
      unsigned char *iData = (unsigned char *)imgData;
      iData += (imageDataLengthInBytes - rowLength); // beginning of last row
      for (int i=0; i < this->AppHelper->GetHeight(); ++i)
        {
        memcpy(b, iData, rowLength);
        b += rowLength;
        iData -= rowLength;
        }
351
      buffer = ((char*) buffer) + imageDataLengthInBytes;
Matt Turek's avatar
Matt Turek committed
352

353
354
355
356
357
      this->UpdateProgress(float(count)/float(numFiles));
      int len = static_cast<int> (strlen((char*) (*fiter).c_str()));
      char* filename = new char[len+1];
      strcpy(filename, (char*) (*fiter).c_str());
      this->SetProgressText(filename);
358
      delete[] filename;
359
      }
Matt Turek's avatar
Matt Turek committed
360
361
362
    }
}

363
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
364
365
void vtkDICOMImageReader::SetupOutputInformation(int num_slices)
{
366
367
368
369
  int width = this->AppHelper->GetWidth();
  int height = this->AppHelper->GetHeight();
  int bit_depth = this->AppHelper->GetBitsAllocated();
  int num_comp = this->AppHelper->GetNumberOfComponents();
Matt Turek's avatar
Matt Turek committed
370

371
372
373
374
375
376
  this->DataExtent[0] = 0;
  this->DataExtent[1] = width - 1;
  this->DataExtent[2] = 0;
  this->DataExtent[3] = height - 1;
  this->DataExtent[4] = 0;
  this->DataExtent[5] = num_slices - 1;
Matt Turek's avatar
Matt Turek committed
377

378
  bool isFloat = this->AppHelper->RescaledImageDataIsFloat();
Matt Turek's avatar
Matt Turek committed
379

380
  bool sign = this->AppHelper->RescaledImageDataIsSigned();
Matt Turek's avatar
Matt Turek committed
381

382
383
384
385
386
387
388
389
390
391
392
  if (isFloat)
    {
    this->SetDataScalarTypeToFloat();
    }
  else if (bit_depth <= 8)
    {
    this->SetDataScalarTypeToUnsignedChar();
    }
  else
    {
    if (sign)
Matt Turek's avatar
Matt Turek committed
393
      {
394
      this->SetDataScalarTypeToShort();
Matt Turek's avatar
Matt Turek committed
395
396
397
      }
    else
      {
398
      this->SetDataScalarTypeToUnsignedShort();
Matt Turek's avatar
Matt Turek committed
399
      }
400
401
    }
  this->SetNumberOfScalarComponents(num_comp);
Matt Turek's avatar
Matt Turek committed
402

403
  this->GetPixelSpacing();
404
405
406
407
  float *pos = this->GetImagePositionPatient();
  this->DataOrigin[0] = pos[0];
  this->DataOrigin[1] = pos[1];
  this->DataOrigin[2] = pos[2];
408

409
  this->vtkImageReader2::ExecuteInformation();
Matt Turek's avatar
Matt Turek committed
410
}
Matt Turek's avatar
Matt Turek committed
411

412
//----------------------------------------------------------------------------
Matt Turek's avatar
Matt Turek committed
413
414
void vtkDICOMImageReader::SetDirectoryName(const char* dn)
{
415
416
417
418
  vtkDebugMacro(<< this->GetClassName() << " (" << this <<
                "): setting DirectoryName to " << (dn ? dn : "(null)") );
  if ( this->DirectoryName == NULL && dn == NULL)
    {
Matt Turek's avatar
Matt Turek committed
419
    return;
420
    }
Ken Martin's avatar
Ken Martin committed
421
  if (this->FileName)
422
423
424
425
    {
    delete [] this->FileName;
    this->FileName = NULL;
    }
426
427
  if ( this->DirectoryName && dn && (!strcmp(this->DirectoryName,dn)))
    {
Ken Martin's avatar
Ken Martin committed
428
429
    return;
    }
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  if (this->DirectoryName)
    {
    delete [] this->DirectoryName;
    }
  if (dn)
    {
    this->DirectoryName = new char[strlen(dn)+1];
    strcpy(this->DirectoryName,dn);
    }
   else
    {
    this->DirectoryName = NULL;
    }
  this->Modified();
Matt Turek's avatar
Matt Turek committed
444
445
}

446
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
447
double* vtkDICOMImageReader::GetPixelSpacing()
448
{
449
  vtkstd::vector<vtkstd::pair<float, vtkstd::string> > sortedFiles;
450

Jim Miller's avatar
Jim Miller committed
451
  this->AppHelper->GetImagePositionPatientFilenamePairs(sortedFiles, false);
452

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  float* spacing = this->AppHelper->GetPixelSpacing();
  this->DataSpacing[0] = spacing[0];
  this->DataSpacing[1] = spacing[1];

  if (sortedFiles.size() > 1)
    {
    vtkstd::pair<float, vtkstd::string> p1 = sortedFiles[0];
    vtkstd::pair<float, vtkstd::string> p2 = sortedFiles[1];
    this->DataSpacing[2] = fabs(p1.first - p2.first);
    }
  else
    {
    this->DataSpacing[2] = spacing[2];
    }

  return this->DataSpacing;
469
}
470

471
//----------------------------------------------------------------------------
472
473
474
475
476
int vtkDICOMImageReader::GetWidth()
{
  return this->AppHelper->GetWidth();
}

477
//----------------------------------------------------------------------------
478
479
480
481
482
int vtkDICOMImageReader::GetHeight()
{
  return this->AppHelper->GetHeight();
}

483
//----------------------------------------------------------------------------
484
485
486
487
488
float* vtkDICOMImageReader::GetImagePositionPatient()
{
  return this->AppHelper->GetImagePositionPatient();
}

489
490
491
492
493
494
//----------------------------------------------------------------------------
float* vtkDICOMImageReader::GetImageOrientationPatient()
{
  return this->AppHelper->GetImageOrientationPatient();
}

495
//----------------------------------------------------------------------------
496
497
498
499
500
int vtkDICOMImageReader::GetBitsAllocated()
{
  return this->AppHelper->GetBitsAllocated();
}

501
//----------------------------------------------------------------------------
502
503
504
505
506
int vtkDICOMImageReader::GetPixelRepresentation()
{
  return this->AppHelper->GetPixelRepresentation();
}

507
//----------------------------------------------------------------------------
508
509
510
511
512
int vtkDICOMImageReader::GetNumberOfComponents()
{
  return this->AppHelper->GetNumberOfComponents();
}

513
//----------------------------------------------------------------------------
514
515
const char* vtkDICOMImageReader::GetTransferSyntaxUID()
{
516
  vtkstd::string tmp = this->AppHelper->GetTransferSyntaxUID();
517

518
519
520
521
522
523
524
525
526
  if (this->TransferSyntaxUID)
    {
    delete [] this->TransferSyntaxUID;
    }
  this->TransferSyntaxUID = new char[tmp.length()+1];
  strcpy(this->TransferSyntaxUID, tmp.c_str());
  this->TransferSyntaxUID[tmp.length()] = '\0';

  return this->TransferSyntaxUID;
527
}
528

529
//----------------------------------------------------------------------------
530
531
532
533
534
float vtkDICOMImageReader::GetRescaleSlope()
{
  return this->AppHelper->GetRescaleSlope();
}

535
//----------------------------------------------------------------------------
536
537
538
539
540
float vtkDICOMImageReader::GetRescaleOffset()
{
  return this->AppHelper->GetRescaleOffset();
}

541
//----------------------------------------------------------------------------
542
543
const char* vtkDICOMImageReader::GetPatientName()
{
544
  vtkstd::string tmp = this->AppHelper->GetPatientName();
545

546
547
548
549
550
551
552
553
554
  if (this->PatientName)
    {
    delete [] this->PatientName;
    }
  this->PatientName = new char[tmp.length()+1];
  strcpy(this->PatientName, tmp.c_str());
  this->PatientName[tmp.length()] = '\0';

  return this->PatientName;
555
556
}

557
//----------------------------------------------------------------------------
558
559
const char* vtkDICOMImageReader::GetStudyUID()
{
560
  vtkstd::string tmp = this->AppHelper->GetStudyUID();
561

562
563
564
565
566
567
568
569
570
571
572
  if (this->StudyUID)
    {
    delete [] this->StudyUID;
    }
  this->StudyUID = new char[tmp.length()+1];
  strcpy(this->StudyUID, tmp.c_str());
  this->StudyUID[tmp.length()] = '\0';

  return this->StudyUID;
}

573
//----------------------------------------------------------------------------
574
575
576
const char* vtkDICOMImageReader::GetStudyID()
{
  vtkstd::string tmp = this->AppHelper->GetStudyID();
577

578
579
580
581
582
583
584
585
586
  if (this->StudyID)
    {
    delete [] this->StudyID;
    }
  this->StudyID = new char[tmp.length()+1];
  strcpy(this->StudyID, tmp.c_str());
  this->StudyID[tmp.length()] = '\0';

  return this->StudyID;
587
588
}

589
//----------------------------------------------------------------------------
590
591
592
593
float vtkDICOMImageReader::GetGantryAngle()
{
  return this->AppHelper->GetGantryAngle();
}
594
595

//----------------------------------------------------------------------------
596
int vtkDICOMImageReader::GetNumberOfDICOMFileNames()
597
598
599
600
601
{
  return static_cast<int>(this->DICOMFileNames->size());
}

//----------------------------------------------------------------------------
602
const char* vtkDICOMImageReader::GetDICOMFileName(int index)
603
{
604
  if(index >= 0 && index < this->GetNumberOfDICOMFileNames())
605
606
607
608
609
610
    {
    return (*this->DICOMFileNames)[index].c_str();
    }
  return 0;
}