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 #include "gdcmFileHelper.h"
00069 #include "gdcmFile.h"
00070 #include "vtkGdcmReader.h"
00071
00072
00073 #include <vtkObjectFactory.h>
00074 #include <vtkImageData.h>
00075 #include <vtkPointData.h>
00076 #include <vtkLookupTable.h>
00077
00078 vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.66 $");
00079 vtkStandardNewMacro(vtkGdcmReader);
00080
00081
00082
00083 vtkGdcmReader::vtkGdcmReader()
00084 {
00085 this->LookupTable = NULL;
00086 this->AllowLookupTable = 0;
00087 }
00088
00089 vtkGdcmReader::~vtkGdcmReader()
00090 {
00091 this->RemoveAllFileName();
00092 this->InternalFileNameList.clear();
00093 if(this->LookupTable)
00094 this->LookupTable->Delete();
00095 }
00096
00097
00098
00099 void vtkGdcmReader::PrintSelf(ostream& os, vtkIndent indent)
00100 {
00101 this->Superclass::PrintSelf(os,indent);
00102 os << indent << "Filenames : " << endl;
00103 vtkIndent nextIndent = indent.GetNextIndent();
00104 for (std::list<std::string>::iterator it = FileNameList.begin();
00105 it != FileNameList.end();
00106 ++it)
00107 {
00108 os << nextIndent << it->c_str() << endl ;
00109 }
00110 }
00111
00112
00113
00114
00115
00116
00117 void vtkGdcmReader::RemoveAllFileName(void)
00118 {
00119 this->FileNameList.clear();
00120 this->Modified();
00121 }
00122
00123
00124
00125
00126 void vtkGdcmReader::AddFileName(const char* name)
00127 {
00128
00129
00130 char * LocalName = new char[strlen(name) + 1];
00131 strcpy(LocalName, name);
00132 this->FileNameList.push_back(LocalName);
00133 delete[] LocalName;
00134 this->Modified();
00135 }
00136
00137
00138
00139
00140 void vtkGdcmReader::SetFileName(const char *name)
00141 {
00142 vtkImageReader2::SetFileName(name);
00143
00144
00145
00146 vtkDebugMacro(<< "Clearing all files given with AddFileName");
00147 this->FileNameList.clear();
00148 this->Modified();
00149 }
00150
00151
00152
00153
00154
00155
00156 void vtkGdcmReader::ExecuteInformation()
00157 {
00158 if(this->MTime>this->fileTime)
00159 {
00160 this->TotalNumberOfPlanes = this->CheckFileCoherence();
00161 if ( this->TotalNumberOfPlanes == 0)
00162 {
00163 vtkErrorMacro(<< "File set is not coherent. Exiting...");
00164 return;
00165 }
00166
00167
00168
00169 if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
00170 (this->DataVOI[4] || this->DataVOI[5]))
00171 {
00172 this->DataExtent[4] = this->DataVOI[4];
00173 this->DataExtent[5] = this->DataVOI[5];
00174 }
00175
00176
00177 if (this->DataVOI[0] || this->DataVOI[1] ||
00178 this->DataVOI[2] || this->DataVOI[3] ||
00179 this->DataVOI[4] || this->DataVOI[5])
00180 {
00181 if ((this->DataVOI[0] < 0) ||
00182 (this->DataVOI[1] >= this->NumColumns) ||
00183 (this->DataVOI[2] < 0) ||
00184 (this->DataVOI[3] >= this->NumLines) ||
00185 (this->DataVOI[4] < 0) ||
00186 (this->DataVOI[5] >= this->TotalNumberOfPlanes ))
00187 {
00188 vtkWarningMacro(<< "The requested VOI is larger than expected extent.");
00189 this->DataVOI[0] = 0;
00190 this->DataVOI[1] = this->NumColumns - 1;
00191 this->DataVOI[2] = 0;
00192 this->DataVOI[3] = this->NumLines - 1;
00193 this->DataVOI[4] = 0;
00194 this->DataVOI[5] = this->TotalNumberOfPlanes - 1;
00195 }
00196 }
00197
00198
00199 this->DataExtent[0] = 0;
00200 this->DataExtent[1] = this->NumColumns - 1;
00201 this->DataExtent[2] = 0;
00202 this->DataExtent[3] = this->NumLines - 1;
00203 this->DataExtent[4] = 0;
00204 this->DataExtent[5] = this->TotalNumberOfPlanes - 1;
00205
00206
00207
00208
00209
00210 if ( ImageType == "8U" )
00211 {
00212 vtkDebugMacro(<< "8 bits unsigned image");
00213 this->SetDataScalarTypeToUnsignedChar();
00214 }
00215 else if ( ImageType == "8S" )
00216 {
00217 vtkErrorMacro(<< "Cannot handle 8 bit signed files");
00218 return;
00219 }
00220 else if ( ImageType == "16U" )
00221 {
00222 vtkDebugMacro(<< "16 bits unsigned image");
00223 this->SetDataScalarTypeToUnsignedShort();
00224 }
00225 else if ( ImageType == "16S" )
00226 {
00227 vtkDebugMacro(<< "16 bits signed image");
00228 this->SetDataScalarTypeToShort();
00229
00230 }
00231 else if ( ImageType == "32U" )
00232 {
00233 vtkDebugMacro(<< "32 bits unsigned image");
00234 vtkDebugMacro(<< "WARNING: forced to signed int !");
00235 this->SetDataScalarTypeToInt();
00236 }
00237 else if ( ImageType == "32S" )
00238 {
00239 vtkDebugMacro(<< "32 bits signed image");
00240 this->SetDataScalarTypeToInt();
00241 }
00242 else if ( ImageType == "FD" )
00243 {
00244 vtkDebugMacro(<< "64 bits Double image");
00245 this->SetDataScalarTypeToDouble();
00246 }
00247
00248 this->SetNumberOfScalarComponents(this->NumComponents);
00249
00250 this->fileTime=this->MTime;
00251 }
00252
00253 this->Superclass::ExecuteInformation();
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263 void vtkGdcmReader::ExecuteData(vtkDataObject *output)
00264 {
00265 if (this->InternalFileNameList.empty())
00266 {
00267 vtkErrorMacro(<< "A least a valid FileName must be specified.");
00268 return;
00269 }
00270
00271
00272 vtkImageData *data = this->AllocateOutputData(output);
00273 data->SetExtent(this->DataExtent);
00274 data->GetPointData()->GetScalars()->SetName("DicomImage-Volume");
00275
00276
00277
00278 if((this->DataExtent[1]-this->DataExtent[0]>=0) &&
00279 (this->DataExtent[3]-this->DataExtent[2]>=0) &&
00280 (this->DataExtent[5]-this->DataExtent[4]>=0))
00281 {
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 unsigned long UpdateProgressTarget = (unsigned long) ceil (this->NumLines
00292 * this->TotalNumberOfPlanes
00293 / 50.0);
00294
00295 unsigned long UpdateProgressCount = 0;
00296
00297
00298 unsigned char *Dest = (unsigned char *)data->GetScalarPointer();
00299 for (std::list<std::string>::iterator filename = InternalFileNameList.begin();
00300 filename != InternalFileNameList.end();
00301 ++filename)
00302 {
00303
00304
00305
00306 if (*filename != "GDCM_UNREADABLE")
00307 {
00308
00309 Dest += this->LoadImageInMemory(*filename, Dest,
00310 UpdateProgressTarget,
00311 UpdateProgressCount);
00312 }
00313 else
00314 {
00315
00316
00317
00318 Dest += this->NumColumns * this->NumLines * this->PixelSize;
00319
00320
00321 UpdateProgressCount += this->NumLines;
00322 if (UpdateProgressTarget > 0)
00323 {
00324 if (!(UpdateProgressCount%UpdateProgressTarget))
00325 {
00326 this->UpdateProgress(UpdateProgressCount/(50.0*UpdateProgressTarget));
00327 }
00328 }
00329 }
00330 }
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 void vtkGdcmReader::BuildFileListFromPattern()
00343 {
00344 this->RemoveAllInternalFileName();
00345
00346 if ((! this->FileNameList.empty()) && this->FileName )
00347 {
00348 vtkErrorMacro(<< "Both AddFileName and SetFileName schemes were used");
00349 vtkErrorMacro(<< "No images loaded ! ");
00350 return;
00351 }
00352
00353 if ((! this->FileNameList.empty()) && this->FilePrefix )
00354 {
00355 vtkErrorMacro(<< "Both AddFileName and SetFilePrefix schemes were used");
00356 vtkErrorMacro(<< "No images loaded ! ");
00357 return;
00358 }
00359
00360 if (this->FileName && this->FilePrefix)
00361 {
00362 vtkErrorMacro(<< "Both SetFileName and SetFilePrefix schemes were used");
00363 vtkErrorMacro(<< "No images loaded ! ");
00364 return;
00365 }
00366
00367 if (! this->FileNameList.empty() )
00368 {
00369 vtkDebugMacro(<< "Using the AddFileName specified files");
00370 this->InternalFileNameList=this->FileNameList;
00371 return;
00372 }
00373
00374 if (!this->FileName && !this->FilePrefix)
00375 {
00376 vtkErrorMacro(<< "FileNames are not set. Either use AddFileName() or");
00377 vtkErrorMacro(<< "specify a FileName or FilePrefix.");
00378 return;
00379 }
00380
00381 if( this->FileName )
00382 {
00383
00384
00385 this->ComputeInternalFileName(this->DataExtent[4]);
00386 vtkDebugMacro(<< "Adding file " << this->InternalFileName);
00387 this->AddInternalFileName(this->InternalFileName);
00388 }
00389 else
00390 {
00391
00392 for (int idx = this->DataExtent[4]; idx <= this->DataExtent[5]; ++idx)
00393 {
00394 this->ComputeInternalFileName(idx);
00395 vtkDebugMacro(<< "Adding file " << this->InternalFileName);
00396 this->AddInternalFileName(this->InternalFileName);
00397 }
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 int vtkGdcmReader::CheckFileCoherence()
00418 {
00419 int ReturnedTotalNumberOfPlanes = 0;
00420
00421 this->BuildFileListFromPattern();
00422 if (this->InternalFileNameList.empty())
00423 {
00424 vtkErrorMacro(<< "FileNames are not set.");
00425 return 0;
00426 }
00427
00428 bool FoundReferenceFile = false;
00429 int ReferenceNZ = 0;
00430
00431
00432
00433
00434 for (std::list<std::string>::iterator filename = InternalFileNameList.begin();
00435 filename != InternalFileNameList.end();
00436 ++filename)
00437 {
00438
00439
00440
00441
00442
00443 ReturnedTotalNumberOfPlanes += 1;
00444
00446 if(*filename == std::string("GDCM_UNREADABLE"))
00447 continue;
00448
00450
00451 FILE *fp;
00452 fp = fopen(filename->c_str(),"rb");
00453 if (!fp)
00454 {
00455 vtkErrorMacro(<< "Unable to open file " << filename->c_str());
00456 vtkErrorMacro(<< "Removing this file from readed files "
00457 << filename->c_str());
00458 *filename = "GDCM_UNREADABLE";
00459 continue;
00460 }
00461 fclose(fp);
00462
00463
00464 gdcm::File GdcmFile(filename->c_str() );
00465 if (!GdcmFile.IsReadable())
00466 {
00467 vtkErrorMacro(<< "Gdcm cannot parse file " << filename->c_str());
00468 vtkErrorMacro(<< "Removing this file from readed files "
00469 << filename->c_str());
00470 *filename = "GDCM_UNREADABLE";
00471 continue;
00472 }
00473
00474
00475 std::string type = GdcmFile.GetPixelType();
00476 if ( (type != "8U") && (type != "8S")
00477 && (type != "16U") && (type != "16S")
00478 && (type != "32U") && (type != "32S") )
00479 {
00480 vtkErrorMacro(<< "Bad File Type for file " << filename->c_str() << "\n"
00481 << " File type found : " << type.c_str()
00482 << " (might be 8U, 8S, 16U, 16S, 32U, 32S) \n"
00483 << " Removing this file from readed files");
00484 *filename = "GDCM_UNREADABLE";
00485 continue;
00486 }
00487
00488
00489 int NX = GdcmFile.GetXSize();
00490 int NY = GdcmFile.GetYSize();
00491 int NZ = GdcmFile.GetZSize();
00492 if (FoundReferenceFile)
00493 {
00494
00495 if ( ( NX != this->NumColumns )
00496 || ( NY != this->NumLines )
00497 || ( type != this->ImageType ) )
00498 {
00499 vtkErrorMacro(<< "This file is not coherent with previous ones"
00500 << filename->c_str());
00501 vtkErrorMacro(<< "Removing this file from readed files "
00502 << filename->c_str());
00503 *filename = "GDCM_UNREADABLE";
00504 continue;
00505 }
00506
00507
00508 if ( NZ != ReferenceNZ )
00509 {
00510 vtkErrorMacro(<< "File is not coherent in Z with previous ones"
00511 << filename->c_str());
00512 }
00513 else
00514 {
00515 vtkDebugMacro(<< "File is coherent with previous ones"
00516 << filename->c_str());
00517 }
00518
00519
00520
00521 if (NZ > 1)
00522 {
00523 vtkErrorMacro(<< "This file contains multiple planes (images)"
00524 << filename->c_str());
00525 }
00526
00527
00528
00529 vtkDebugMacro("Number of planes added to the stack: " << NZ);
00530 ReturnedTotalNumberOfPlanes += NZ - 1;
00531 continue;
00532
00533 }
00534 else
00535 {
00536
00537
00538 FoundReferenceFile = true;
00539 vtkDebugMacro(<< "This file taken as coherence reference:"
00540 << filename->c_str());
00541 vtkDebugMacro(<< "Image dimension of reference file as read from Gdcm:"
00542 << NX << " " << NY << " " << NZ);
00543 vtkDebugMacro(<< "Number of planes added to the stack: " << NZ);
00544
00545 this->NumColumns = NX;
00546 this->NumLines = NY;
00547 ReferenceNZ = NZ;
00548 ReturnedTotalNumberOfPlanes += NZ - 1;
00549 this->ImageType = type;
00550 this->PixelSize = GdcmFile.GetPixelSize();
00551
00552 if( GdcmFile.HasLUT() && this->AllowLookupTable )
00553 {
00554
00555 this->NumComponents = GdcmFile.GetNumberOfScalarComponentsRaw();
00556 }
00557 else
00558 {
00559 this->NumComponents = GdcmFile.GetNumberOfScalarComponents();
00560 }
00561
00562
00563 this->DataSpacing[0] = GdcmFile.GetXSpacing();
00564 this->DataSpacing[1] = GdcmFile.GetYSpacing();
00565 this->DataSpacing[2] = GdcmFile.GetZSpacing();
00566
00567
00568
00569
00570
00571
00572 }
00573 }
00574
00576
00577 int NumberCoherentFiles = 0;
00578 for (std::list<std::string>::iterator it = InternalFileNameList.begin();
00579 it != InternalFileNameList.end();
00580 ++it)
00581 {
00582 if (*it != "GDCM_UNREADABLE")
00583 {
00584 NumberCoherentFiles++;
00585 }
00586 }
00587 vtkDebugMacro(<< "Number of coherent files: " << NumberCoherentFiles);
00588
00589 if (ReturnedTotalNumberOfPlanes == 0)
00590 {
00591 vtkErrorMacro(<< "No loadable file.");
00592 }
00593
00594 vtkDebugMacro(<< "Total number of planes on the stack: "
00595 << ReturnedTotalNumberOfPlanes);
00596
00597 return ReturnedTotalNumberOfPlanes;
00598 }
00599
00600
00601
00602
00603
00604
00605 void vtkGdcmReader::RemoveAllInternalFileName(void)
00606 {
00607 this->InternalFileNameList.clear();
00608 }
00609
00610
00611
00612
00613 void vtkGdcmReader::AddInternalFileName(const char* name)
00614 {
00615 char * LocalName = new char[strlen(name) + 1];
00616 strcpy(LocalName, name);
00617 this->InternalFileNameList.push_back(LocalName);
00618 delete[] LocalName;
00619 }
00620
00621
00622
00623
00624
00625 size_t vtkGdcmReader::LoadImageInMemory(
00626 std::string fileName,
00627 unsigned char *dest,
00628 const unsigned long updateProgressTarget,
00629 unsigned long & updateProgressCount)
00630 {
00631 vtkDebugMacro(<< "Copying to memory image [" << fileName.c_str() << "]");
00632 gdcm::FileHelper file( fileName.c_str() );
00633 size_t size;
00634
00635
00636
00637
00638
00639
00640
00641
00642 int numColumns = file.GetFile()->GetXSize();
00643 int numLines = file.GetFile()->GetYSize();
00644 int numPlanes = file.GetFile()->GetZSize();
00645 int lineSize = NumComponents * numColumns * file.GetFile()->GetPixelSize();
00646 int planeSize = lineSize * numLines;
00647
00648 unsigned char *src;
00649
00650 if( file.GetFile()->HasLUT() && AllowLookupTable )
00651 {
00652 size = file.GetImageDataSize();
00653 src = (unsigned char*) file.GetImageDataRaw();
00654 unsigned char *lut = (unsigned char*) file.GetLutRGBA();
00655
00656 if(!this->LookupTable)
00657 {
00658 this->LookupTable = vtkLookupTable::New();
00659 }
00660
00661 this->LookupTable->SetNumberOfTableValues(256);
00662 for (int tmp=0; tmp<256; tmp++)
00663 {
00664 this->LookupTable->SetTableValue(tmp,
00665 (float)lut[4*tmp+0]/255.0,
00666 (float)lut[4*tmp+1]/255.0,
00667 (float)lut[4*tmp+2]/255.0,
00668 1);
00669 }
00670 this->LookupTable->SetRange(0,255);
00671 vtkDataSetAttributes *a = this->GetOutput()->GetPointData();
00672 a->GetScalars()->SetLookupTable(this->LookupTable);
00673 free(lut);
00674 }
00675 else
00676 {
00677 size = file.GetImageDataSize();
00678 src = (unsigned char*)file.GetImageData();
00679 }
00680
00681 unsigned char *dst = dest + planeSize - lineSize;
00682 for (int plane = 0; plane < numPlanes; plane++)
00683 {
00684 for (int line = 0; line < numLines; line++)
00685 {
00686
00687 memcpy((void*)dst, (void*)src, lineSize);
00688 src += lineSize;
00689 dst -= lineSize;
00690
00691 if (!(updateProgressCount%updateProgressTarget))
00692 {
00693 this->UpdateProgress(updateProgressCount/(50.0*updateProgressTarget));
00694 }
00695 updateProgressCount++;
00696 }
00697 dst += 2 * planeSize;
00698 }
00699
00700 return size;
00701 }
00702
00703