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

vtkGdcmWriter.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002                                                                                 
00003   Program:   gdcm
00004   Module:    $RCSfile: vtkGdcmWriter.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2005/10/25 14:52:37 $
00007   Version:   $Revision: 1.26 $
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 #include "gdcmFile.h"
00020 #include "gdcmFileHelper.h"
00021 #include "gdcmDebug.h"
00022 #include "gdcmUtil.h"
00023 #include "vtkGdcmWriter.h"
00024 
00025 #include <vtkObjectFactory.h>
00026 #include <vtkImageData.h>
00027 #include <vtkPointData.h>
00028 #include <vtkLookupTable.h>
00029 
00030 #ifndef vtkFloatingPointType
00031 #define vtkFloatingPointType float
00032 #endif
00033 
00034 vtkCxxRevisionMacro(vtkGdcmWriter, "$Revision: 1.26 $")
00035 vtkStandardNewMacro(vtkGdcmWriter)
00036 
00037 //-----------------------------------------------------------------------------
00038 // Constructor / Destructor
00039 vtkGdcmWriter::vtkGdcmWriter()
00040 {
00041    this->LookupTable = NULL;
00042    this->FileDimensionality = 3;
00043    this->WriteType = VTK_GDCM_WRITE_TYPE_EXPLICIT_VR;
00044 }
00045 
00046 vtkGdcmWriter::~vtkGdcmWriter()
00047 {
00048 }
00049 
00050 //-----------------------------------------------------------------------------
00051 // Print
00052 void vtkGdcmWriter::PrintSelf(ostream &os, vtkIndent indent)
00053 {
00054    this->Superclass::PrintSelf(os, indent);
00055 
00056    os << indent << "Write type : " << this->GetWriteTypeAsString();
00057 }
00058 
00059 //-----------------------------------------------------------------------------
00060 // Public
00061 const char *vtkGdcmWriter::GetWriteTypeAsString()
00062 {
00063    switch(WriteType)
00064    {
00065       case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
00066          return "Explicit VR";
00067       case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
00068          return "Implicit VR";
00069       case VTK_GDCM_WRITE_TYPE_ACR :
00070          return "ACR";
00071       case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
00072          return "ACR Libido";
00073       default :
00074          return "Unknow type";
00075    }
00076 }
00077 
00078 //-----------------------------------------------------------------------------
00079 // Protected
00083 // The output data must be deleted by the user of the method !!!
00084 size_t ReverseData(vtkImageData *image,unsigned char **data)
00085 {
00086    int inc[3];
00087    int *extent = image->GetUpdateExtent();
00088    int dim[3] = {extent[1]-extent[0]+1,
00089                  extent[3]-extent[2]+1,
00090                  extent[5]-extent[4]+1};
00091 
00092    size_t lineSize = dim[0] * image->GetScalarSize()
00093                    * image->GetNumberOfScalarComponents();
00094    size_t planeSize = dim[1] * lineSize;
00095    size_t size = dim[2] * planeSize;
00096 
00097    if( size>0 )
00098    {
00099       *data = new unsigned char[size];
00100 
00101       image->GetIncrements(inc);
00102       unsigned char *src = (unsigned char *)image->GetScalarPointerForExtent(extent);
00103       unsigned char *dst = *data + planeSize - lineSize;
00104       for (int plane = extent[4]; plane <= extent[5]; plane++)
00105       {
00106          for (int line = extent[2]; line <= extent[3]; line++)
00107          {
00108             // Copy one line at proper destination:
00109             memcpy((void*)dst, (void*)src, lineSize);
00110 
00111             src += inc[1] * image->GetScalarSize();
00112             dst -= lineSize;
00113          }
00114          dst += 2 * planeSize;
00115       }
00116    }
00117    else
00118    {
00119       *data = NULL;
00120    }
00121 
00122    return size;
00123 }
00124 
00128 void SetImageInformation(gdcm::FileHelper *file, vtkImageData *image)
00129 {
00130    std::ostringstream str;
00131 
00132    // Image size
00133    int *extent = image->GetUpdateExtent();
00134    int dim[3] = {extent[1]-extent[0]+1,
00135                  extent[3]-extent[2]+1,
00136                  extent[5]-extent[4]+1};
00137 
00138    str.str("");
00139    str << dim[0];
00140    file->InsertEntryString(str.str(),0x0028,0x0011); // Columns
00141 
00142    str.str("");
00143    str << dim[1];
00144    file->InsertEntryString(str.str(),0x0028,0x0010); // Rows
00145 
00146    if(dim[2]>1)
00147    {
00148       str.str("");
00149       str << dim[2];
00150       //file->Insert(str.str(),0x0028,0x0012); // Planes
00151       file->InsertEntryString(str.str(),0x0028,0x0008); // Number of Frames
00152    }
00153 
00154    // Pixel type
00155    str.str("");
00156    str << image->GetScalarSize()*8;
00157    file->InsertEntryString(str.str(),0x0028,0x0100); // Bits Allocated
00158    file->InsertEntryString(str.str(),0x0028,0x0101); // Bits Stored
00159 
00160    str.str("");
00161    str << image->GetScalarSize()*8-1;
00162    file->InsertEntryString(str.str(),0x0028,0x0102); // High Bit
00163 
00164    // Pixel Repr
00165    // FIXME : what do we do when the ScalarType is 
00166    // VTK_UNSIGNED_INT or VTK_UNSIGNED_LONG
00167    str.str("");
00168    if( image->GetScalarType() == VTK_UNSIGNED_CHAR  ||
00169        image->GetScalarType() == VTK_UNSIGNED_SHORT ||
00170        image->GetScalarType() == VTK_UNSIGNED_INT   ||
00171        image->GetScalarType() == VTK_UNSIGNED_LONG )
00172    {
00173       str << "0"; // Unsigned
00174    }
00175    else
00176    {
00177       str << "1"; // Signed
00178    }
00179    file->InsertEntryString(str.str(),0x0028,0x0103); // Pixel Representation
00180 
00181    // Samples per pixel
00182    str.str("");
00183    str << image->GetNumberOfScalarComponents();
00184    file->InsertEntryString(str.str(),0x0028,0x0002); // Samples per Pixel
00185 
00188 
00189    // Spacing
00190    vtkFloatingPointType *sp = image->GetSpacing();
00191 
00192    str.str("");
00193    // We are about to enter floating point value. 
00194    // By default ostringstream are smart and don't do fixed point
00195    // thus forcing to fixed point value
00196    str.setf( std::ios::fixed );
00197    str << sp[1] << "\\" << sp[0];
00198    file->InsertEntryString(str.str(),0x0028,0x0030); // Pixel Spacing
00199    str.str("");
00200    str << sp[2];
00201    file->InsertEntryString(str.str(),0x0018,0x0088); // Spacing Between Slices
00202 
00203    // Origin
00204    vtkFloatingPointType *org = image->GetOrigin();
00205 
00208 
00209    str.str("");
00210    str << org[0] << "\\" << org[1] << "\\" << org[2];
00211    file->InsertEntryString(str.str(),0x0020,0x0032); // Image Position Patient
00212    str.unsetf( std::ios::fixed ); //done with floating point values
00213 
00214    // Window / Level
00215    vtkFloatingPointType *rng = image->GetScalarRange();
00216 
00217    str.str("");
00218    str << rng[1]-rng[0];
00219    file->InsertEntryString(str.str(),0x0028,0x1051); // Window Width
00220    str.str("");
00221    str << (rng[1]+rng[0])/2.0;
00222    file->InsertEntryString(str.str(),0x0028,0x1050); // Window Center
00223 
00224    // Pixels
00225    unsigned char *data;
00226    size_t size = ReverseData(image,&data);
00227    file->SetUserData(data,size);
00228 }
00229 
00234 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *image, 
00235                     ofstream *file)
00236 {
00237    if(file)
00238    {
00239       vtkErrorMacro( <<  "File must not be open");
00240       return;
00241    }
00242 
00243    if( image->GetScalarType() == VTK_FLOAT || 
00244        image->GetScalarType() == VTK_DOUBLE )
00245    {
00246       vtkErrorMacro(<< "Bad input type. Scalar type must not be of type "
00247                     << "VTK_FLOAT or VTKDOUBLE (found:"
00248                     << image->GetScalarTypeAsString());
00249       return;
00250    }
00251 
00252    RecursiveWrite(axis,image, image, file);
00253    //WriteDcmFile(this->FileName,image);
00254 }
00255 
00256 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache, 
00257                                    vtkImageData *image, ofstream *file)
00258 {
00259    int idx, min, max;
00260 
00261    // if the file is already open then just write to it
00262    if( file )
00263    {
00264       vtkErrorMacro( <<  "File musn't be open");
00265       return;
00266    }
00267 
00268    // if we need to open another slice, do it
00269    if( (axis + 1) == this->FileDimensionality )
00270    {
00271       // determine the name
00272       if (this->FileName)
00273       {
00274          sprintf(this->InternalFileName, "%s", this->FileName);
00275       }
00276       else 
00277       {
00278          if (this->FilePrefix)
00279          {
00280             sprintf(this->InternalFileName, this->FilePattern, 
00281             this->FilePrefix, this->FileNumber);
00282          }
00283          else
00284          {
00285             sprintf(this->InternalFileName, this->FilePattern,this->FileNumber);
00286          }
00287 // Remove this code in case user is using VTK 4.2...
00288 #if !(VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION == 2)
00289          if (this->FileNumber < this->MinimumFileNumber)
00290          {
00291             this->MinimumFileNumber = this->FileNumber;
00292          }
00293          else if (this->FileNumber > this->MaximumFileNumber)
00294          {
00295             this->MaximumFileNumber = this->FileNumber;
00296          }
00297 #endif
00298       }
00299 
00300       // Write the file
00301       WriteDcmFile(this->InternalFileName,image);
00302       ++this->FileNumber;
00303       return;
00304    }
00305 
00306    // if the current region is too high a dimension for the file
00307    // the we will split the current axis
00308    cache->GetAxisUpdateExtent(axis, min, max);
00309 
00310    // if it is the y axis then flip by default
00311    if (axis == 1 && !this->FileLowerLeft)
00312    {
00313       for(idx = max; idx >= min; idx--)
00314       {
00315          cache->SetAxisUpdateExtent(axis, idx, idx);
00316          this->RecursiveWrite(axis - 1, cache, image, file);
00317       }
00318    }
00319    else
00320    {
00321       for(idx = min; idx <= max; idx++)
00322       {
00323          cache->SetAxisUpdateExtent(axis, idx, idx);
00324          this->RecursiveWrite(axis - 1, cache, image, file);
00325       }
00326    }
00327 
00328    // restore original extent
00329    cache->SetAxisUpdateExtent(axis, min, max);
00330 }
00331 
00332 void vtkGdcmWriter::WriteDcmFile(char *fileName, vtkImageData *image)
00333 {
00334    // From here, the write of the file begins
00335    gdcm::FileHelper *dcmFile = gdcm::FileHelper::New();
00336 
00337    // Set the image informations
00338    SetImageInformation(dcmFile, image);
00339 
00340    // Write the image
00341    switch(this->WriteType)
00342    {
00343       case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
00344          dcmFile->SetWriteTypeToDcmExplVR();
00345          break;
00346       case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
00347          dcmFile->SetWriteTypeToDcmImplVR();
00348          break;
00349       case VTK_GDCM_WRITE_TYPE_ACR :
00350          dcmFile->SetWriteTypeToAcr();
00351          break;
00352       case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
00353          dcmFile->SetWriteTypeToAcrLibido();
00354          break;
00355       default :
00356          dcmFile->SetWriteTypeToDcmExplVR();
00357    }
00358 
00359    if(!dcmFile->Write(fileName))
00360    {
00361       vtkErrorMacro( << "File "  <<  this->FileName  <<  "cannot be written by "
00362                      << " the gdcm library");
00363    }
00364 
00365    // Clean up
00366    if( dcmFile->GetUserData() && dcmFile->GetUserDataSize()>0 )
00367    {
00368       delete[] dcmFile->GetUserData();
00369    }
00370    dcmFile->Delete();
00371 }
00372 
00373 //-----------------------------------------------------------------------------
00374 // Private
00375 
00376 //-----------------------------------------------------------------------------

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