Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

vtkGdcmReader.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002                                                                                 
00003   Program:   gdcm
00004   Module:    $RCSfile: vtkGdcmReader.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2005/10/25 14:52:37 $
00007   Version:   $Revision: 1.85 $
00008                                                                                 
00009   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
00010   l'Image). All rights reserved. See Doc/License.txt or
00011   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
00012                                                                                 
00013      This software is distributed WITHOUT ANY WARRANTY; without even
00014      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00015      PURPOSE.  See the above copyright notices for more information.
00016                                                                                 
00017 =========================================================================*/
00018                                                                                 
00019 //-----------------------------------------------------------------------------
00020 // //////////////////////////////////////////////////////////////
00021 //
00022 //===>  Many users expect from vtkGdcmReader it 'orders' the images
00023 //     (that's the job of gdcm::SerieHelper ...)
00024 //     When user *knows* the files with same Serie UID 
00025 //        have same sizes, same 'pixel' type, same color convention, ...
00026 //     the right way to proceed is as follow :
00027 //
00028 //      gdcm::SerieHelper *sh= new gdcm::SerieHelper();
00029 //      // if user wants *not* to load some parts of the file headers
00030 //      sh->SetLoadMode(loadMode);
00031 //      // if user wants *not* to load some files 
00032 //      sh->AddRestriction(group, element, value, operator);
00033 //      sh->AddRestriction( ...
00034 //      sh->SetDirectory(directoryWithImages);
00035 //
00036 //      // if user wants to sort reverse order
00037 //      sh->SetSortOrderToReverse(); 
00038 //      // here, we suppose only the first Coherent File List is of interest
00039 //      gdcm::FileList *l = sh->GetFirstCoherentFileList();
00040 //      // if user is doesn't trust too much the files with same Serie UID 
00041 //      if ( !sh->IsCoherent(l) )
00042 //         return; // not same sizes, same 'pixel' type -> stop
00043 //      sh->OrderFileList(l);        // sort the list
00044 //
00045 //      vtkGdcmReader *reader = vtkGdcmReader::New();
00046 //      // if user wants to modify pixel order (Mirror, TopDown, 90°Rotate, ...)
00047 //      // he has to supply the function that does the job 
00048 //      // (a *very* simple example is given in vtkgdcmSerieViewer.cxx)
00049 //      reader->SetUserFunction (userSuppliedFunction);
00050 //      // to pass a 'Coherent File List' as produced by gdcm::SerieHelper
00051 //      reader->SetCoherentFileList(l); 
00052 //      reader->Update();
00053 //
00054 // WARNING TODO CLEANME 
00055 // Actual limitations of this code 
00056 //  when a Coherent File List from SerieHelper is not used (bad idea :-(
00057 //
00058 // //////////////////////////////////////////////////////////////
00059 
00060 #include "gdcmFileHelper.h"
00061 #include "gdcmFile.h"
00062 
00063 #include "vtkGdcmReader.h"
00064 #include "gdcmDebug.h"
00065 #include "gdcmCommon.h"
00066 
00067 #include <vtkObjectFactory.h>
00068 #include <vtkImageData.h>
00069 #include <vtkPointData.h>
00070 #include <vtkLookupTable.h>
00071 
00072 vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.85 $")
00073 vtkStandardNewMacro(vtkGdcmReader)
00074 
00075 //-----------------------------------------------------------------------------
00076 // Constructor / Destructor
00077 vtkGdcmReader::vtkGdcmReader()
00078 {
00079    this->LookupTable = NULL;
00080    this->AllowLookupTable = false;
00081    this->AllowLightChecking = false;
00082    this->LoadMode = gdcm::LD_ALL; // Load everything (possible values : 
00083                                  //  - LD_NOSEQ, 
00084                                  //  - LD_NOSHADOW,
00085                                  //  - LD_NOSHADOWSEQ)
00086    this->CoherentFileList = 0;
00087    this->UserFunction     = 0;
00088 
00089    this->OwnFile=true;
00090    this->Execution=false;
00091 }
00092 
00093 vtkGdcmReader::~vtkGdcmReader()
00094 {
00095    this->RemoveAllFileName();
00096    this->InternalFileNameList.clear();
00097    if(this->LookupTable) 
00098       this->LookupTable->Delete();
00099 }
00100 
00101 //-----------------------------------------------------------------------------
00102 // Print
00103 void vtkGdcmReader::PrintSelf(ostream &os, vtkIndent indent)
00104 {
00105    this->Superclass::PrintSelf(os,indent);
00106    os << indent << "Filenames  : " << endl;
00107    vtkIndent nextIndent = indent.GetNextIndent();
00108    for (std::list<std::string>::iterator it = FileNameList.begin();
00109         it != FileNameList.end();
00110         ++it)
00111    {
00112       os << nextIndent << it->c_str() << endl ;
00113    }
00114 }
00115 
00116 //-----------------------------------------------------------------------------
00117 // Public
00118 /*
00119  * Remove all files from the list of images to read.
00120  */
00121 void vtkGdcmReader::RemoveAllFileName(void)
00122 {
00123    this->FileNameList.clear();
00124    this->Modified();
00125 }
00126 
00127 /*
00128  * Adds a file name to the list of images to read.
00129  */
00130 void vtkGdcmReader::AddFileName(const char* name)
00131 {
00132    // We need to bypass the const pointer [since list<>.push_bash() only
00133    // takes a char* (but not a const char*)] by making a local copy:
00134    this->FileNameList.push_back(name);
00135    this->Modified();
00136 }
00137 
00138 /*
00139  * Sets up a filename to be read.
00140  */
00141 void vtkGdcmReader::SetFileName(const char *name) 
00142 {
00143    vtkImageReader2::SetFileName(name);
00144    // Since we maintain a list of filenames, when building a volume,
00145    // (see vtkGdcmReader::AddFileName), we additionaly need to purge
00146    // this list when we manually positionate the filename.
00147    vtkDebugMacro(<< "Clearing all files given with AddFileName");
00148    this->FileNameList.clear();
00149    this->Modified();
00150 }
00151 
00152 //-----------------------------------------------------------------------------
00153 // Protected
00154 /*
00155  * Configure the output e.g. WholeExtent, spacing, origin, scalar type...
00156  */
00157 void vtkGdcmReader::ExecuteInformation()
00158 {
00159    if(this->Execution)
00160       return;
00161 
00162    this->Execution=true;
00163    this->RemoveAllInternalFile();
00164    if(this->MTime>this->fileTime)
00165    {
00166       this->TotalNumberOfPlanes = 0;
00167 
00168       if ( this->CoherentFileList != 0 )
00169       {
00170          this->UpdateFileInformation();
00171       }
00172       else
00173       {
00174          this->BuildFileListFromPattern();
00175          this->LoadFileInformation();
00176       }
00177 
00178       if ( this->TotalNumberOfPlanes == 0)
00179       {
00180          vtkErrorMacro(<< "File set is not coherent. Exiting...");
00181          return;
00182       }
00183 
00184       // if the user has not set the extent, but has set the VOI
00185       // set the z axis extent to the VOI z axis
00186       if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
00187          (this->DataVOI[4] || this->DataVOI[5]))
00188       {
00189          this->DataExtent[4] = this->DataVOI[4];
00190          this->DataExtent[5] = this->DataVOI[5];
00191       }
00192 
00193       // When the user has set the VOI, check it's coherence with the file content.
00194       if (this->DataVOI[0] || this->DataVOI[1] || 
00195       this->DataVOI[2] || this->DataVOI[3] ||
00196       this->DataVOI[4] || this->DataVOI[5])
00197       { 
00198          if ((this->DataVOI[0] < 0) ||
00199              (this->DataVOI[1] >= this->NumColumns) ||
00200              (this->DataVOI[2] < 0) ||
00201              (this->DataVOI[3] >= this->NumLines) ||
00202              (this->DataVOI[4] < 0) ||
00203              (this->DataVOI[5] >= this->TotalNumberOfPlanes ))
00204          {
00205             vtkWarningMacro(<< "The requested VOI is larger than expected extent.");
00206             this->DataVOI[0] = 0;
00207             this->DataVOI[1] = this->NumColumns - 1;
00208             this->DataVOI[2] = 0;
00209             this->DataVOI[3] = this->NumLines - 1;
00210             this->DataVOI[4] = 0;
00211             this->DataVOI[5] = this->TotalNumberOfPlanes - 1;
00212          }
00213       }
00214 
00215       // Set the Extents.
00216       this->DataExtent[0] = 0;
00217       this->DataExtent[1] = this->NumColumns - 1;
00218       this->DataExtent[2] = 0;
00219       this->DataExtent[3] = this->NumLines - 1;
00220       this->DataExtent[4] = 0;
00221       this->DataExtent[5] = this->TotalNumberOfPlanes - 1;
00222   
00223       // We don't need to set the Endian related stuff (by using
00224       // this->SetDataByteOrderToBigEndian() or SetDataByteOrderToLittleEndian()
00225       // since the reading of the file is done by gdcm.
00226       // But we do need to set up the data type for downstream filters:
00227       if      ( ImageType == "8U" )
00228       {
00229          vtkDebugMacro(<< "8 bits unsigned image");
00230          this->SetDataScalarTypeToUnsignedChar(); 
00231       }
00232       else if ( ImageType == "8S" )
00233       {
00234          vtkErrorMacro(<< "Cannot handle 8 bit signed files");
00235          return;
00236       }
00237       else if ( ImageType == "16U" )
00238       {
00239          vtkDebugMacro(<< "16 bits unsigned image");
00240          this->SetDataScalarTypeToUnsignedShort();
00241       }
00242       else if ( ImageType == "16S" )
00243       {
00244          vtkDebugMacro(<< "16 bits signed image");
00245          this->SetDataScalarTypeToShort();
00246       }
00247       else if ( ImageType == "32U" )
00248       {
00249          vtkDebugMacro(<< "32 bits unsigned image");
00250          vtkDebugMacro(<< "WARNING: forced to signed int !");
00251          this->SetDataScalarTypeToInt();
00252       }
00253       else if ( ImageType == "32S" )
00254       {
00255          vtkDebugMacro(<< "32 bits signed image");
00256          this->SetDataScalarTypeToInt();
00257       }
00258       else if ( ImageType == "FD" )
00259       {
00260          vtkDebugMacro(<< "64 bits Double image");
00261          this->SetDataScalarTypeToDouble();
00262       }
00263       //Set number of scalar components:
00264       this->SetNumberOfScalarComponents(this->NumComponents);
00265 
00266       this->fileTime=this->MTime;
00267    }
00268 
00269    this->Superclass::ExecuteInformation();
00270 
00271    this->GetOutput()->SetUpdateExtentToWholeExtent();
00272    this->BuildData(this->GetOutput());
00273 
00274    this->Execution=false;
00275    this->RemoveAllInternalFile();
00276 }
00277  
00278 /*
00279  * Update => ouput->Update => UpdateData => Execute => ExecuteData 
00280  * (see vtkSource.cxx for last step).
00281  * This function (redefinition of vtkImageReader::ExecuteData, see 
00282  * VTK/IO/vtkImageReader.cxx) reads a data from a file. The data
00283  * extent/axes are assumed to be the same as the file extent/order.
00284  */
00285 void vtkGdcmReader::ExecuteData(vtkDataObject *output)
00286 {
00287    vtkImageData *data=vtkImageData::SafeDownCast(output);
00288    data->SetExtent(this->DataExtent);
00289 
00290 /*   if ( CoherentFileList != 0 )   // When a list of names is passed
00291    {
00292       if (this->CoherentFileList->empty())
00293       {
00294          vtkErrorMacro(<< "Coherent File List must have at least a valid File*.");
00295          return;
00296       }
00297    }
00298    else if (this->InternalFileNameList.empty())
00299    {
00300       vtkErrorMacro(<< "A least a valid FileName must be specified.");
00301       return;
00302    }
00303 */
00304 }
00305 
00306 void vtkGdcmReader::BuildData(vtkDataObject *output)
00307 {
00308    vtkImageData *data = this->AllocateOutputData(output);
00309 
00310    data->GetPointData()->GetScalars()->SetName("DicomImage-Volume");
00311 
00312    // Test if output has valid extent
00313    // Prevent memory errors
00314    if((this->DataExtent[1]-this->DataExtent[0]>=0) &&
00315       (this->DataExtent[3]-this->DataExtent[2]>=0) &&
00316       (this->DataExtent[5]-this->DataExtent[4]>=0))
00317    {
00318       // The memory size for a full stack of images of course depends
00319       // on the number of planes and the size of each image:
00320       //size_t StackNumPixels = this->NumColumns * this->NumLines
00321       //                      * this->TotalNumberOfPlanes * this->NumComponents;
00322       //size_t stack_size = StackNumPixels * this->PixelSize; //not used
00323       // Allocate pixel data space itself.
00324 
00325       // Variables for the UpdateProgress. We shall use 50 steps to signify
00326       // the advance of the process:
00327       unsigned long UpdateProgressTarget = (unsigned long) ceil (this->NumLines
00328                                          * this->TotalNumberOfPlanes
00329                                          / 50.0);
00330       // The actual advance measure:
00331       unsigned long UpdateProgressCount = 0;
00332 
00333       // Filling the allocated memory space with each image/volume:
00334 
00335       size_t size = this->NumColumns * this->NumLines * this->NumPlanes
00336                   * data->GetScalarSize() * this->NumComponents;
00337       unsigned char *Dest = (unsigned char *)data->GetScalarPointer();
00338       for (std::vector<gdcm::File* >::iterator it =  InternalFileList.begin();
00339                                                it != InternalFileList.end();
00340                                              ++it)
00341       {
00342          this->LoadImageInMemory(*it, Dest,
00343                                  UpdateProgressTarget,
00344                                  UpdateProgressCount); 
00345          Dest += size;
00346       }
00347    }
00348 }
00349 
00350 /*
00351  * vtkGdcmReader can have the file names specified through two ways:
00352  * (1) by calling the vtkImageReader2::SetFileName(), SetFilePrefix() and
00353  *     SetFilePattern()
00354  * (2) By successive calls to vtkGdcmReader::AddFileName()
00355  * When the first method was used by caller we need to update the local
00356  * filename list
00357  */
00358 void vtkGdcmReader::BuildFileListFromPattern()
00359 {
00360    this->RemoveAllInternalFileName();
00361 
00362    // Test miscellanous cases
00363    if ((! this->FileNameList.empty()) && this->FileName )
00364    {
00365       vtkErrorMacro(<< "Both AddFileName and SetFileName schemes were used");
00366       vtkErrorMacro(<< "No images loaded ! ");
00367       return;
00368    }
00369 
00370    if ((! this->FileNameList.empty()) && this->FilePrefix )
00371    {
00372       vtkErrorMacro(<< "Both AddFileName and SetFilePrefix schemes were used");
00373       vtkErrorMacro(<< "No images loaded ! ");
00374       return;
00375    }
00376 
00377    if (this->FileName && this->FilePrefix)
00378    {
00379       vtkErrorMacro(<< "Both SetFileName and SetFilePrefix schemes were used");
00380       vtkErrorMacro(<< "No images loaded ! ");
00381       return;
00382    }
00383 
00384    // Create the InternalFileNameList
00385    if (! this->FileNameList.empty()  )
00386    {
00387       vtkDebugMacro(<< "Using the AddFileName specified files");
00388       this->InternalFileNameList=this->FileNameList;
00389       return;
00390    }
00391 
00392    if (!this->FileName && !this->FilePrefix)
00393    {
00394       vtkErrorMacro(<< "FileNames are not set. Either use AddFileName() or");
00395       vtkErrorMacro(<< "specify a FileName or FilePrefix.");
00396       return;
00397    }
00398 
00399    if( this->FileName )
00400    {
00401       // Single file loading (as given with ::SetFileName()):
00402       // Case of multi-frame file considered here
00403       this->ComputeInternalFileName(this->DataExtent[4]);
00404       vtkDebugMacro(<< "Adding file " << this->InternalFileName);
00405       this->AddInternalFileName(this->InternalFileName);
00406    }
00407    else
00408    {
00409       // Multi file loading (as given with ::SetFilePattern()):
00410       for (int idx = this->DataExtent[4]; idx <= this->DataExtent[5]; ++idx)
00411       {
00412          this->ComputeInternalFileName(idx);
00413          vtkDebugMacro(<< "Adding file " << this->InternalFileName);
00414          this->AddInternalFileName(this->InternalFileName);
00415       }
00416    }
00417 }
00418 
00429 void vtkGdcmReader::LoadFileInformation()
00430 {
00431    gdcm::File *file;
00432    bool foundReference=false;
00433    std::string type;
00434 
00435    this->OwnFile=true;
00436    for (std::list<std::string>::iterator filename = InternalFileNameList.begin();
00437         filename != InternalFileNameList.end();
00438         ++filename)
00439    {
00440       // check for file readability
00441       FILE *fp;
00442       fp = fopen(filename->c_str(),"rb");
00443       if (!fp)
00444       {
00445          vtkErrorMacro(<< "Unable to open file " << filename->c_str());
00446          vtkErrorMacro(<< "Removing this file from read files: "
00447                        << filename->c_str());
00448          file = NULL;
00449          InternalFileList.push_back(file);
00450          continue;
00451       }
00452       fclose(fp);
00453 
00454       // Read the file
00455       file=gdcm::File::New();
00456       file->SetLoadMode( LoadMode );
00457       file->SetFileName(filename->c_str() );
00458       file->Load();
00459 
00460       // Test the Dicom file readability
00461       if(!file->IsReadable())
00462       {
00463          vtkErrorMacro(<< "Gdcm cannot parse file " << filename->c_str());
00464          vtkErrorMacro(<< "Removing this file from read files: "
00465                         << filename->c_str());
00466          file->Delete();
00467          file=NULL;
00468          InternalFileList.push_back(file);
00469          continue;
00470       }
00471 
00472       // Test the Pixel Type recognition
00473       type = file->GetPixelType();
00474       if (   (type !=  "8U") && (type !=  "8S")
00475           && (type != "16U") && (type != "16S")
00476           && (type != "32U") && (type != "32S") )
00477       {
00478          vtkErrorMacro(<< "Bad File Type for file " << filename->c_str() << "\n"
00479                        << "   File type found : " << type.c_str() 
00480                        << " (might be 8U, 8S, 16U, 16S, 32U, 32S) \n"
00481                        << "   Removing this file from read files");
00482          file->Delete();
00483          file=NULL;
00484          InternalFileList.push_back(file);
00485          continue;
00486       }
00487 
00488       // Test the image informations
00489       if(!foundReference)
00490       {
00491          foundReference = true;
00492          GetFileInformation(file);
00493 
00494          vtkDebugMacro(<< "This file taken as coherence reference:"
00495                         << filename->c_str());
00496          vtkDebugMacro(<< "Image dimensions of reference file as read from Gdcm:" 
00497                         << this->NumColumns << " " << this->NumLines << " " 
00498                         << this->NumPlanes);
00499       }
00500       else if(!TestFileInformation(file))
00501       {
00502          file->Delete();
00503          file=NULL;
00504       }
00505 
00506       InternalFileList.push_back(file);
00507    }
00508 }
00509 
00515 void vtkGdcmReader::UpdateFileInformation()
00516 {
00517    this->InternalFileList=*(this->CoherentFileList);
00518    this->OwnFile=false;
00519 
00520    for(gdcmFileList::iterator it=InternalFileList.begin();
00521                               it!=InternalFileList.end();
00522                               ++it)
00523    {
00524       if( *it != NULL)
00525       {
00526          GetFileInformation(*it);
00527          break;
00528       }
00529    }
00530 }
00531 
00537 void vtkGdcmReader::GetFileInformation(gdcm::File *file)
00538 {
00539    // Get the image caracteristics
00540    this->NumColumns = file->GetXSize();
00541    this->NumLines   = file->GetYSize();
00542    this->NumPlanes  = file->GetZSize();
00543 
00544    if (CoherentFileList == 0)
00545       this->TotalNumberOfPlanes = this->NumPlanes*InternalFileNameList.size();
00546    else
00547       this->TotalNumberOfPlanes = this->NumPlanes*CoherentFileList->size();
00548 
00549    this->ImageType = file->GetPixelType();
00550    this->PixelSize = file->GetPixelSize();
00551 
00552    this->DataSpacing[0] = file->GetXSpacing();
00553    this->DataSpacing[1] = file->GetYSpacing();
00554    this->DataSpacing[2] = file->GetZSpacing();
00555 
00556    // Get the image data caracteristics
00557    if( file->HasLUT() && this->AllowLookupTable )
00558    {
00559       // I could raise an error is AllowLookupTable is on and HasLUT() off
00560       this->NumComponents = file->GetNumberOfScalarComponentsRaw();
00561    }
00562    else
00563    {
00564       this->NumComponents = file->GetNumberOfScalarComponents(); //rgb or mono
00565    }
00566 }
00567 
00568 /*
00569  * When more than one filename is specified (i.e. we expect loading
00570  * a stack or volume) we need to check that the corresponding images/volumes
00571  * to be loaded are coherent i.e. to make sure:
00572  *     - they all share the same X dimensions
00573  *     - they all share the same Y dimensions
00574  *     - they all share the same ImageType ( 8 bit signed, or unsigned...)
00575  *
00576  * Eventually, we emit a warning when all the files do NOT share the
00577  * Z dimension, since we can still build a stack but the
00578  * files are not coherent in Z, which is probably a source a trouble...
00579  *   When files are not readable (either the file cannot be opened or
00580  * because gdcm cannot parse it), they are flagged as "GDCM_UNREADABLE".  
00581  *   This method returns the total number of planar images to be loaded
00582  * (i.e. an image represents one plane, but a volume represents many planes)
00583  */
00595 bool vtkGdcmReader::TestFileInformation(gdcm::File *file)
00596 {
00597    int numColumns = file->GetXSize();
00598    int numLines   = file->GetYSize();
00599    int numPlanes  = file->GetZSize();
00600    int numComponents;
00601    unsigned int pixelSize  = file->GetPixelSize();
00602 
00603    if( file->HasLUT() && this->AllowLookupTable )
00604       numComponents = file->GetNumberOfScalarComponentsRaw();
00605    else
00606       numComponents = file->GetNumberOfScalarComponents(); //rgb or mono
00607 
00608    if( numColumns != this->NumColumns )
00609    {
00610       vtkErrorMacro(<< "File X value doesn't match with the previous ones: "
00611                     << file->GetFileName().c_str()
00612                     << ". Found " << numColumns << ", must be "
00613                     << this->NumColumns);
00614       return false;
00615    }
00616    if( numLines != this->NumLines )
00617    {
00618       vtkErrorMacro(<< "File Y value doesn't match with the previous ones: "
00619                     << file->GetFileName().c_str()
00620                     << ". Found " << numLines << ", must be "
00621                     << this->NumLines);
00622       return false;
00623    }
00624    if( numPlanes != this->NumPlanes )
00625    {
00626       vtkErrorMacro(<< "File Z value doesn't match with the previous ones: "
00627                     << file->GetFileName().c_str()
00628                     << ". Found " << numPlanes << ", must be "
00629                     << this->NumPlanes);
00630       return false;
00631    }
00632    if( numComponents != this->NumComponents )
00633    {
00634       vtkErrorMacro(<< "File Components count doesn't match with the previous ones: "
00635                     << file->GetFileName().c_str()
00636                     << ". Found " << numComponents << ", must be "
00637                     << this->NumComponents);
00638       return false;
00639    }
00640    if( pixelSize != this->PixelSize )
00641    {
00642       vtkErrorMacro(<< "File pixel size doesn't match with the previous ones: "
00643                     << file->GetFileName().c_str()
00644                     << ". Found " << pixelSize << ", must be "
00645                     << this->PixelSize);
00646       return false;
00647    }
00648 
00649    return true;
00650 }
00651 
00652 //-----------------------------------------------------------------------------
00653 // Private
00654 /*
00655  * Remove all file names to the internal list of images to read.
00656  */
00657 void vtkGdcmReader::RemoveAllInternalFileName(void)
00658 {
00659    this->InternalFileNameList.clear();
00660 }
00661 
00662 /*
00663  * Adds a file name to the internal list of images to read.
00664  */
00665 void vtkGdcmReader::AddInternalFileName(const char *name)
00666 {
00667    char *LocalName = new char[strlen(name) + 1];
00668    strcpy(LocalName, name);
00669    this->InternalFileNameList.push_back(LocalName);
00670    delete[] LocalName;
00671 }
00672 
00673 /*
00674  * Remove all file names to the internal list of images to read.
00675  */
00676 void vtkGdcmReader::RemoveAllInternalFile(void)
00677 {
00678    if(this->OwnFile)
00679    {
00680       for(gdcmFileList::iterator it=InternalFileList.begin();
00681                                  it!=InternalFileList.end();
00682                                  ++it)
00683       {
00684          (*it)->Delete();
00685       }
00686    }
00687    this->InternalFileList.clear();
00688 }
00689 
00690 void vtkGdcmReader::IncrementProgress(const unsigned long updateProgressTarget,
00691                                       unsigned long &updateProgressCount)
00692 {
00693    // Update progress related for bad files:
00694    updateProgressCount += this->NumLines;
00695    if (updateProgressTarget > 0)
00696    {
00697       if (!(updateProgressCount%updateProgressTarget))
00698       {
00699          this->UpdateProgress(updateProgressCount/(50.0*updateProgressTarget));
00700       }
00701    }
00702 }
00703 
00704 /*
00705  * Loads the contents of the image/volume contained by char *fileName at
00706  * the dest memory address. Returns the size of the data loaded.
00707  */
00708 /*void vtkGdcmReader::LoadImageInMemory(
00709              std::string fileName, 
00710              unsigned char *dest,
00711              const unsigned long updateProgressTarget,
00712              unsigned long &updateProgressCount)
00713 {
00714    vtkDebugMacro(<< "Copying to memory image [" << fileName.c_str() << "]");
00715 
00716    gdcm::File *f;
00717    f = new gdcm::File();
00718    f->SetLoadMode( LoadMode );
00719    f->SetFileName( fileName.c_str() );
00720    f->Load( );
00721 
00722    LoadImageInMemory(f,dest,
00723                      updateProgressTarget,
00724                      updateProgressCount);
00725    delete f;
00726 }*/
00727 
00728 /*
00729  * Loads the contents of the image/volume contained by gdcm::File* f at
00730  * the Dest memory address. Returns the size of the data loaded.
00731  * \ param f File to consider. NULL if the file must be skiped
00732  * \remarks Assume that if (f != NULL) then its caracteristics match
00733  * with the previous ones
00734  */
00735 void vtkGdcmReader::LoadImageInMemory(
00736              gdcm::File *f, 
00737              unsigned char *dest,
00738              const unsigned long updateProgressTarget,
00739              unsigned long &updateProgressCount)
00740 {
00741    if(!f)
00742       return;
00743 
00744    gdcm::FileHelper *fileH = gdcm::FileHelper::New( f );
00745    fileH->SetUserFunction( UserFunction );
00746 
00747    int numColumns = f->GetXSize();
00748    int numLines   = f->GetYSize();
00749    int numPlanes  = f->GetZSize();
00750    int numComponents;
00751 
00752    if( f->HasLUT() && this->AllowLookupTable )
00753       numComponents = f->GetNumberOfScalarComponentsRaw();
00754    else
00755       numComponents = f->GetNumberOfScalarComponents(); //rgb or mono
00756    vtkDebugMacro(<< "numComponents:" << numComponents);
00757    vtkDebugMacro(<< "Copying to memory image [" << f->GetFileName().c_str() << "]");
00758    //size_t size;
00759 
00760    // If the data structure of vtk for image/volume representation
00761    // were straigthforwards the following would be enough:
00762    //    GdcmFile.GetImageDataIntoVector((void*)Dest, size);
00763    // But vtk chooses to invert the lines of an image, that is the last
00764    // line comes first (for some axis related reasons?). Hence we need
00765    // to load the image line by line, starting from the end.
00766 
00767    int lineSize   = NumComponents * numColumns * f->GetPixelSize();
00768    int planeSize  = lineSize * numLines;
00769 
00770    unsigned char *src;
00771    
00772    if( fileH->GetFile()->HasLUT() && AllowLookupTable )
00773    {
00774       // to avoid bcc 5.5 w
00775       /*size               = */ fileH->GetImageDataSize(); 
00776       src                = (unsigned char*) fileH->GetImageDataRaw();
00777       unsigned char *lut = (unsigned char*) fileH->GetLutRGBA();
00778 
00779       if(!this->LookupTable)
00780       {
00781          this->LookupTable = vtkLookupTable::New();
00782       }
00783 
00784       this->LookupTable->SetNumberOfTableValues(256);
00785       for (int tmp=0; tmp<256; tmp++)
00786       {
00787          this->LookupTable->SetTableValue(tmp,
00788          (float)lut[4*tmp+0]/255.0,
00789          (float)lut[4*tmp+1]/255.0,
00790          (float)lut[4*tmp+2]/255.0,
00791          1);
00792       }
00793       this->LookupTable->SetRange(0,255);
00794       vtkDataSetAttributes *a = this->GetOutput()->GetPointData();
00795       a->GetScalars()->SetLookupTable(this->LookupTable);
00796       free(lut);
00797    }
00798    else
00799    {
00800       //size = fileH->GetImageDataSize(); 
00801       // useless - just an accessor;  'size' unused
00802       src  = (unsigned char*)fileH->GetImageData();  
00803    } 
00804 
00805    unsigned char *dst = dest + planeSize - lineSize;
00806    for (int plane = 0; plane < numPlanes; plane++)
00807    {
00808       for (int line = 0; line < numLines; line++)
00809       {
00810          // Copy one line at proper destination:
00811          memcpy((void*)dst, (void*)src, lineSize);
00812          src += lineSize;
00813          dst -= lineSize;
00814          // Update progress related:
00815          if (!(updateProgressCount%updateProgressTarget))
00816          {
00817             this->UpdateProgress(updateProgressCount/(50.0*updateProgressTarget));
00818          }
00819          updateProgressCount++;
00820       }
00821       dst += 2 * planeSize;
00822    }
00823 
00824    fileH->Delete();
00825 }
00826 
00827 //-----------------------------------------------------------------------------

Generated on Fri Jan 20 10:14:26 2006 for gdcm by  doxygen 1.4.4