00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #include "gdcmFileHelper.h"
00083 #include "gdcmFile.h"
00084 #include "gdcmSerieHelper.h"
00085
00086 #include "vtkGdcmReader.h"
00087 #include "gdcmDebug.h"
00088 #include "gdcmCommon.h"
00089
00090 #include <vtkObjectFactory.h>
00091 #include <vtkImageData.h>
00092 #include <vtkPointData.h>
00093 #include <vtkLookupTable.h>
00094
00095 vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.91 $")
00096 vtkStandardNewMacro(vtkGdcmReader)
00097
00098
00099
00100 vtkGdcmReader::vtkGdcmReader()
00101 {
00102 this->LookupTable = NULL;
00103 this->AllowLookupTable = false;
00104
00105 this->LoadMode = GDCM_NAME_SPACE::LD_ALL;
00106
00107
00108
00109 this->CoherentFileList = 0;
00110 this->UserFunction = 0;
00111
00112 this->OwnFile=true;
00113
00114 }
00115
00116 vtkGdcmReader::~vtkGdcmReader()
00117 {
00118 this->RemoveAllFileName();
00119 this->InternalFileNameList.clear();
00120 if(this->LookupTable)
00121 this->LookupTable->Delete();
00122 }
00123
00124
00125
00126 void vtkGdcmReader::PrintSelf(ostream &os, vtkIndent indent)
00127 {
00128 this->Superclass::PrintSelf(os,indent);
00129 os << indent << "Filenames : " << endl;
00130 vtkIndent nextIndent = indent.GetNextIndent();
00131 for (std::list<std::string>::iterator it = FileNameList.begin();
00132 it != FileNameList.end();
00133 ++it)
00134 {
00135 os << nextIndent << it->c_str() << endl ;
00136 }
00137 }
00138
00139
00140
00141
00142
00143
00144 void vtkGdcmReader::RemoveAllFileName(void)
00145 {
00146 this->FileNameList.clear();
00147 this->Modified();
00148 }
00149
00150
00151
00152
00153 void vtkGdcmReader::AddFileName(const char* name)
00154 {
00155
00156
00157 this->FileNameList.push_back(name);
00158 this->Modified();
00159 }
00160
00161
00162
00163
00164 void vtkGdcmReader::SetFileName(const char *name)
00165 {
00166 vtkImageReader2::SetFileName(name);
00167
00168
00169
00170 vtkDebugMacro(<< "Clearing all files given with AddFileName");
00171 this->FileNameList.clear();
00172 this->Modified();
00173 }
00174
00175
00176
00177
00178
00179
00180 void vtkGdcmReader::ExecuteInformation()
00181 {
00182
00183
00184
00185
00186 this->RemoveAllInternalFile();
00187 if(this->MTime>this->fileTime)
00188 {
00189 this->TotalNumberOfPlanes = 0;
00190
00191 if ( this->CoherentFileList != 0 )
00192 {
00193 this->UpdateFileInformation();
00194 }
00195 else
00196 {
00197 this->BuildFileListFromPattern();
00198 this->LoadFileInformation();
00199 }
00200
00201 if ( this->TotalNumberOfPlanes == 0)
00202 {
00203 vtkErrorMacro(<< "File set is not coherent. Exiting...");
00204 return;
00205 }
00206
00207
00208
00209 if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
00210 (this->DataVOI[4] || this->DataVOI[5]))
00211 {
00212 this->DataExtent[4] = this->DataVOI[4];
00213 this->DataExtent[5] = this->DataVOI[5];
00214 }
00215
00216
00217 if (this->DataVOI[0] || this->DataVOI[1] ||
00218 this->DataVOI[2] || this->DataVOI[3] ||
00219 this->DataVOI[4] || this->DataVOI[5])
00220 {
00221 if ((this->DataVOI[0] < 0) ||
00222 (this->DataVOI[1] >= this->NumColumns) ||
00223 (this->DataVOI[2] < 0) ||
00224 (this->DataVOI[3] >= this->NumLines) ||
00225 (this->DataVOI[4] < 0) ||
00226 (this->DataVOI[5] >= this->TotalNumberOfPlanes ))
00227 {
00228 vtkWarningMacro(<< "The requested VOI is larger than expected extent.");
00229 this->DataVOI[0] = 0;
00230 this->DataVOI[1] = this->NumColumns - 1;
00231 this->DataVOI[2] = 0;
00232 this->DataVOI[3] = this->NumLines - 1;
00233 this->DataVOI[4] = 0;
00234 this->DataVOI[5] = this->TotalNumberOfPlanes - 1;
00235 }
00236 }
00237
00238
00239 this->DataExtent[0] = 0;
00240 this->DataExtent[1] = this->NumColumns - 1;
00241 this->DataExtent[2] = 0;
00242 this->DataExtent[3] = this->NumLines - 1;
00243 this->DataExtent[4] = 0;
00244 this->DataExtent[5] = this->TotalNumberOfPlanes - 1;
00245
00246
00247
00248
00249
00250 if ( ImageType == "8U" )
00251 {
00252 vtkDebugMacro(<< "8 bits unsigned image");
00253 this->SetDataScalarTypeToUnsignedChar();
00254 }
00255 else if ( ImageType == "8S" )
00256 {
00257 vtkErrorMacro(<< "Cannot handle 8 bit signed files");
00258 return;
00259 }
00260 else if ( ImageType == "16U" )
00261 {
00262 vtkDebugMacro(<< "16 bits unsigned image");
00263 this->SetDataScalarTypeToUnsignedShort();
00264 }
00265 else if ( ImageType == "16S" )
00266 {
00267 vtkDebugMacro(<< "16 bits signed image");
00268 this->SetDataScalarTypeToShort();
00269 }
00270 else if ( ImageType == "32U" )
00271 {
00272 vtkDebugMacro(<< "32 bits unsigned image");
00273 vtkDebugMacro(<< "WARNING: forced to signed int !");
00274 this->SetDataScalarTypeToInt();
00275 }
00276 else if ( ImageType == "32S" )
00277 {
00278 vtkDebugMacro(<< "32 bits signed image");
00279 this->SetDataScalarTypeToInt();
00280 }
00281 else if ( ImageType == "FD" )
00282 {
00283 vtkDebugMacro(<< "64 bits Double image");
00284 this->SetDataScalarTypeToDouble();
00285 }
00286
00287 this->SetNumberOfScalarComponents(this->NumComponents);
00288
00289 this->fileTime=this->MTime;
00290 }
00291
00292 this->Superclass::ExecuteInformation();
00293
00294
00295
00296
00297
00298
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308 void vtkGdcmReader::ExecuteData(vtkDataObject *output)
00309 {
00310 vtkImageData *data=vtkImageData::SafeDownCast(output);
00311 data->SetExtent(this->DataExtent);
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 data->AllocateScalars();
00336 if (this->UpdateExtentIsEmpty(output))
00337 {
00338 return;
00339 }
00340
00341
00342
00343
00344
00345 data->GetPointData()->GetScalars()->SetName("DicomImage-Volume");
00346
00347
00348
00349 if((this->DataExtent[1]-this->DataExtent[0]>=0) &&
00350 (this->DataExtent[3]-this->DataExtent[2]>=0) &&
00351 (this->DataExtent[5]-this->DataExtent[4]>=0))
00352 {
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 unsigned long UpdateProgressTarget = (unsigned long) ceil (this->NumLines
00363 * this->TotalNumberOfPlanes
00364 / 50.0);
00365
00366 unsigned long UpdateProgressCount = 0;
00367
00368
00369
00370 size_t size = this->NumColumns * this->NumLines * this->NumPlanes
00371 * data->GetScalarSize() * this->NumComponents;
00372 unsigned char *Dest = (unsigned char *)data->GetScalarPointer();
00373 for (std::vector<GDCM_NAME_SPACE::File* >::iterator it = InternalFileList.begin();
00374 it != InternalFileList.end();
00375 ++it)
00376 {
00377 this->LoadImageInMemory(*it, Dest,
00378 UpdateProgressTarget,
00379 UpdateProgressCount);
00380 Dest += size;
00381 }
00382 }
00383 this->RemoveAllInternalFile();
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 void vtkGdcmReader::BuildFileListFromPattern()
00395 {
00396 this->RemoveAllInternalFileName();
00397
00398
00399 if ((! this->FileNameList.empty()) && this->FileName )
00400 {
00401 vtkErrorMacro(<< "Both AddFileName and SetFileName schemes were used");
00402 vtkErrorMacro(<< "No images loaded ! ");
00403 return;
00404 }
00405
00406 if ((! this->FileNameList.empty()) && this->FilePrefix )
00407 {
00408 vtkErrorMacro(<< "Both AddFileName and SetFilePrefix schemes were used");
00409 vtkErrorMacro(<< "No images loaded ! ");
00410 return;
00411 }
00412
00413 if (this->FileName && this->FilePrefix)
00414 {
00415 vtkErrorMacro(<< "Both SetFileName and SetFilePrefix schemes were used");
00416 vtkErrorMacro(<< "No images loaded ! ");
00417 return;
00418 }
00419
00420
00421 if (! this->FileNameList.empty() )
00422 {
00423 vtkDebugMacro(<< "Using the AddFileName specified files");
00424 this->InternalFileNameList=this->FileNameList;
00425 return;
00426 }
00427
00428 if (!this->FileName && !this->FilePrefix)
00429 {
00430 vtkErrorMacro(<< "FileNames are not set. Either use AddFileName() or");
00431 vtkErrorMacro(<< "specify a FileName or FilePrefix.");
00432 return;
00433 }
00434
00435 if( this->FileName )
00436 {
00437
00438
00439 this->ComputeInternalFileName(this->DataExtent[4]);
00440 vtkDebugMacro(<< "Adding file " << this->InternalFileName);
00441 this->AddInternalFileName(this->InternalFileName);
00442 }
00443 else
00444 {
00445
00446 for (int idx = this->DataExtent[4]; idx <= this->DataExtent[5]; ++idx)
00447 {
00448 this->ComputeInternalFileName(idx);
00449 vtkDebugMacro(<< "Adding file " << this->InternalFileName);
00450 this->AddInternalFileName(this->InternalFileName);
00451 }
00452 }
00453 }
00454
00465 void vtkGdcmReader::LoadFileInformation()
00466 {
00467 GDCM_NAME_SPACE::File *file;
00468 bool foundReference=false;
00469 std::string type;
00470
00471 this->OwnFile=true;
00472 for (std::list<std::string>::iterator filename = InternalFileNameList.begin();
00473 filename != InternalFileNameList.end();
00474 ++filename)
00475 {
00476
00477 FILE *fp;
00478 fp = fopen(filename->c_str(),"rb");
00479 if (!fp)
00480 {
00481 vtkErrorMacro(<< "Unable to open file " << filename->c_str());
00482 vtkErrorMacro(<< "Removing this file from read files: "
00483 << filename->c_str());
00484 file = NULL;
00485 InternalFileList.push_back(file);
00486 continue;
00487 }
00488 fclose(fp);
00489
00490
00491 file=GDCM_NAME_SPACE::File::New();
00492 file->SetLoadMode( LoadMode );
00493 file->SetFileName(filename->c_str() );
00494 file->Load();
00495
00496
00497 if(!file->IsReadable())
00498 {
00499 vtkErrorMacro(<< "Gdcm cannot parse file " << filename->c_str());
00500 vtkErrorMacro(<< "Removing this file from read files: "
00501 << filename->c_str());
00502 file->Delete();
00503 file=NULL;
00504 InternalFileList.push_back(file);
00505 continue;
00506 }
00507
00508
00509 type = file->GetPixelType();
00510 if ( (type != "8U") && (type != "8S")
00511 && (type != "16U") && (type != "16S")
00512 && (type != "32U") && (type != "32S") )
00513 {
00514 vtkErrorMacro(<< "Bad File Type for file " << filename->c_str() << "\n"
00515 << " File type found : " << type.c_str()
00516 << " (might be 8U, 8S, 16U, 16S, 32U, 32S) \n"
00517 << " Removing this file from read files");
00518 file->Delete();
00519 file=NULL;
00520 InternalFileList.push_back(file);
00521 continue;
00522 }
00523
00524
00525 if(!foundReference)
00526 {
00527 foundReference = true;
00528 GetFileInformation(file);
00529
00530 vtkDebugMacro(<< "This file taken as coherence reference:"
00531 << filename->c_str());
00532 vtkDebugMacro(<< "Image dimensions of reference file as read from Gdcm:"
00533 << this->NumColumns << " " << this->NumLines << " "
00534 << this->NumPlanes);
00535 }
00536 else if(!TestFileInformation(file))
00537 {
00538 file->Delete();
00539 file=NULL;
00540 }
00541
00542 InternalFileList.push_back(file);
00543 }
00544 }
00545
00551 void vtkGdcmReader::UpdateFileInformation()
00552 {
00553 this->InternalFileList=*(this->CoherentFileList);
00554 this->OwnFile=false;
00555
00556 for(gdcmFileList::iterator it=InternalFileList.begin();
00557 it!=InternalFileList.end();
00558 ++it)
00559 {
00560 if( *it != NULL)
00561 {
00562 GetFileInformation(*it);
00563 break;
00564 }
00565 }
00566 }
00567
00573 void vtkGdcmReader::GetFileInformation(GDCM_NAME_SPACE::File *file)
00574 {
00575
00576 this->NumColumns = file->GetXSize();
00577 this->NumLines = file->GetYSize();
00578 this->NumPlanes = file->GetZSize();
00579
00580 if (CoherentFileList == 0)
00581 this->TotalNumberOfPlanes = this->NumPlanes*InternalFileNameList.size();
00582 else
00583 this->TotalNumberOfPlanes = this->NumPlanes*CoherentFileList->size();
00584
00585 this->ImageType = file->GetPixelType();
00586 this->PixelSize = file->GetPixelSize();
00587
00588 this->DataSpacing[0] = file->GetXSpacing();
00589 this->DataSpacing[1] = file->GetYSpacing();
00590
00591
00592
00593
00594
00595 if (CoherentFileList == 0)
00596 this->DataSpacing[2] = file->GetZSpacing();
00597 else
00598 {
00599
00600
00601 GDCM_NAME_SPACE::SerieHelper *sh = GDCM_NAME_SPACE::SerieHelper::New();
00602 sh->OrderFileList(CoherentFileList);
00603 this->DataSpacing[2] = sh->GetZSpacing();
00604 sh->Delete();
00605 }
00606
00607
00608 if( file->HasLUT() && this->AllowLookupTable )
00609 {
00610
00611 this->NumComponents = file->GetNumberOfScalarComponentsRaw();
00612 }
00613 else
00614 {
00615 this->NumComponents = file->GetNumberOfScalarComponents();
00616 }
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00646 bool vtkGdcmReader::TestFileInformation(GDCM_NAME_SPACE::File *file)
00647 {
00648 int numColumns = file->GetXSize();
00649 int numLines = file->GetYSize();
00650 int numPlanes = file->GetZSize();
00651 int numComponents;
00652 unsigned int pixelSize = file->GetPixelSize();
00653
00654 if( file->HasLUT() && this->AllowLookupTable )
00655 numComponents = file->GetNumberOfScalarComponentsRaw();
00656 else
00657 numComponents = file->GetNumberOfScalarComponents();
00658
00659 if( numColumns != this->NumColumns )
00660 {
00661 vtkErrorMacro(<< "File X value doesn't match with the previous ones: "
00662 << file->GetFileName().c_str()
00663 << ". Found " << numColumns << ", must be "
00664 << this->NumColumns);
00665 return false;
00666 }
00667 if( numLines != this->NumLines )
00668 {
00669 vtkErrorMacro(<< "File Y value doesn't match with the previous ones: "
00670 << file->GetFileName().c_str()
00671 << ". Found " << numLines << ", must be "
00672 << this->NumLines);
00673 return false;
00674 }
00675 if( numPlanes != this->NumPlanes )
00676 {
00677 vtkErrorMacro(<< "File Z value doesn't match with the previous ones: "
00678 << file->GetFileName().c_str()
00679 << ". Found " << numPlanes << ", must be "
00680 << this->NumPlanes);
00681 return false;
00682 }
00683 if( numComponents != this->NumComponents )
00684 {
00685 vtkErrorMacro(<< "File Components count doesn't match with the previous ones: "
00686 << file->GetFileName().c_str()
00687 << ". Found " << numComponents << ", must be "
00688 << this->NumComponents);
00689 return false;
00690 }
00691 if( pixelSize != this->PixelSize )
00692 {
00693 vtkErrorMacro(<< "File pixel size doesn't match with the previous ones: "
00694 << file->GetFileName().c_str()
00695 << ". Found " << pixelSize << ", must be "
00696 << this->PixelSize);
00697 return false;
00698 }
00699
00700 return true;
00701 }
00702
00703
00704
00705
00706
00707
00708 void vtkGdcmReader::RemoveAllInternalFileName(void)
00709 {
00710 this->InternalFileNameList.clear();
00711 }
00712
00713
00714
00715
00716 void vtkGdcmReader::AddInternalFileName(const char *name)
00717 {
00718 char *LocalName = new char[strlen(name) + 1];
00719 strcpy(LocalName, name);
00720 this->InternalFileNameList.push_back(LocalName);
00721 delete[] LocalName;
00722 }
00723
00724
00725
00726
00727 void vtkGdcmReader::RemoveAllInternalFile(void)
00728 {
00729 if(this->OwnFile)
00730 {
00731 for(gdcmFileList::iterator it=InternalFileList.begin();
00732 it!=InternalFileList.end();
00733 ++it)
00734 {
00735 (*it)->Delete();
00736 }
00737 }
00738 this->InternalFileList.clear();
00739 }
00740
00741 void vtkGdcmReader::IncrementProgress(const unsigned long updateProgressTarget,
00742 unsigned long &updateProgressCount)
00743 {
00744
00745 updateProgressCount += this->NumLines;
00746 if (updateProgressTarget > 0)
00747 {
00748 if (!(updateProgressCount%updateProgressTarget))
00749 {
00750 this->UpdateProgress(
00751 updateProgressCount/(50.0*updateProgressTarget));
00752 }
00753 }
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 void vtkGdcmReader::LoadImageInMemory(
00788 GDCM_NAME_SPACE::File *f,
00789 unsigned char *dest,
00790 const unsigned long updateProgressTarget,
00791 unsigned long &updateProgressCount)
00792 {
00793 if(!f)
00794 return;
00795
00796 GDCM_NAME_SPACE::FileHelper *fileH = GDCM_NAME_SPACE::FileHelper::New( f );
00797 fileH->SetUserFunction( UserFunction );
00798
00799 int numColumns = f->GetXSize();
00800 int numLines = f->GetYSize();
00801 int numPlanes = f->GetZSize();
00802 int numComponents;
00803
00804 if( f->HasLUT() && this->AllowLookupTable )
00805 numComponents = f->GetNumberOfScalarComponentsRaw();
00806 else
00807 numComponents = f->GetNumberOfScalarComponents();
00808 vtkDebugMacro(<< "numComponents:" << numComponents);
00809 vtkDebugMacro(<< "Copying to memory image [" << f->GetFileName().c_str() << "]");
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 int lineSize = NumComponents * numColumns * f->GetPixelSize();
00820 int planeSize = lineSize * numLines;
00821
00822 unsigned char *src;
00823
00824 if( fileH->GetFile()->HasLUT() && AllowLookupTable )
00825 {
00826
00827 fileH->GetImageDataSize();
00828 src = (unsigned char*) fileH->GetImageDataRaw();
00829 unsigned char *lut = (unsigned char*) fileH->GetLutRGBA();
00830
00831 if(!this->LookupTable)
00832 {
00833 this->LookupTable = vtkLookupTable::New();
00834 }
00835
00836 this->LookupTable->SetNumberOfTableValues(256);
00837 for (int tmp=0; tmp<256; tmp++)
00838 {
00839 this->LookupTable->SetTableValue(tmp,
00840 (float)lut[4*tmp+0]/255.0,
00841 (float)lut[4*tmp+1]/255.0,
00842 (float)lut[4*tmp+2]/255.0,
00843 1);
00844 }
00845 this->LookupTable->SetRange(0,255);
00846 vtkDataSetAttributes *a = this->GetOutput()->GetPointData();
00847 a->GetScalars()->SetLookupTable(this->LookupTable);
00848 free(lut);
00849 }
00850 else
00851 {
00852
00853
00854 src = (unsigned char*)fileH->GetImageData();
00855 }
00856
00857 unsigned char *dst = dest + planeSize - lineSize;
00858 for (int plane = 0; plane < numPlanes; plane++)
00859 {
00860 for (int line = 0; line < numLines; line++)
00861 {
00862
00863 memcpy((void*)dst, (void*)src, lineSize);
00864 src += lineSize;
00865 dst -= lineSize;
00866
00867 if (!(updateProgressCount%updateProgressTarget))
00868 {
00869 this->UpdateProgress(
00870 updateProgressCount/(50.0*updateProgressTarget));
00871 }
00872 updateProgressCount++;
00873 }
00874 dst += 2 * planeSize;
00875 }
00876
00877 fileH->Delete();
00878 }
00879
00880