Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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/01/28 10:07:35 $
00007   Version:   $Revision: 1.16 $
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 vtkCxxRevisionMacro(vtkGdcmWriter, "$Revision: 1.16 $");
00031 vtkStandardNewMacro(vtkGdcmWriter);
00032 
00033 //-----------------------------------------------------------------------------
00034 // Constructor / Destructor
00035 vtkGdcmWriter::vtkGdcmWriter()
00036 {
00037    this->LookupTable = NULL;
00038    this->FileDimensionality = 3;
00039    this->WriteType = VTK_GDCM_WRITE_TYPE_EXPLICIT_VR;
00040 
00041    UIDPrefix = "";
00042    StudyInstanceUID = "";
00043    SeriesInstanceUID = "";
00044    FrameOfReferenceInstanceUID = "";
00045 }
00046 
00047 vtkGdcmWriter::~vtkGdcmWriter()
00048 {
00049 }
00050 
00051 //-----------------------------------------------------------------------------
00052 // Print
00053 void vtkGdcmWriter::PrintSelf(ostream& os, vtkIndent indent)
00054 {
00055    this->Superclass::PrintSelf(os,indent);
00056 
00057    os << indent << "Write type : " << this->GetWriteTypeAsString();
00058 }
00059 
00060 //-----------------------------------------------------------------------------
00061 // Public
00062 const char *vtkGdcmWriter::GetWriteTypeAsString()
00063 {
00064    switch(WriteType)
00065    {
00066       case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
00067          return "Explicit VR";
00068       case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
00069          return "Implicit VR";
00070       case VTK_GDCM_WRITE_TYPE_ACR :
00071          return "ACR";
00072       case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
00073          return "ACR Libido";
00074       default :
00075          return "Unknow type";
00076    }
00077 }
00078 
00079 void vtkGdcmWriter::SetUIDPrefix(const char *prefix)
00080 {
00081    UIDPrefix = prefix;
00082 }
00083 
00084 const char *vtkGdcmWriter::GetUIDPrefix()
00085 {
00086    return UIDPrefix.c_str();
00087 }
00088 
00089 void vtkGdcmWriter::NewStudyInstanceUID()
00090 {
00091    StudyInstanceUID = "";
00092 }
00093 
00094 void vtkGdcmWriter::NewSeriesInstanceUID()
00095 {
00096    SeriesInstanceUID = "";
00097 }
00098 
00099 void vtkGdcmWriter::NewFrameOfReferenceInstanceUID()
00100 {
00101    FrameOfReferenceInstanceUID = "";
00102 }
00103 
00104 //-----------------------------------------------------------------------------
00105 // Protected
00109 // The output datas must be deleted by the user of the method !!!
00110 size_t ReverseData(vtkImageData *image,unsigned char **data)
00111 {
00112    int inc[3];
00113    int *extent = image->GetUpdateExtent();
00114    int dim[3] = {extent[1]-extent[0]+1,
00115                  extent[3]-extent[2]+1,
00116                  extent[5]-extent[4]+1};
00117 
00118    size_t lineSize = dim[0] * image->GetScalarSize()
00119                    * image->GetNumberOfScalarComponents();
00120    size_t planeSize = dim[1] * lineSize;
00121    size_t size = dim[2] * planeSize;
00122 
00123    if( size>0 )
00124    {
00125       *data = new unsigned char[size];
00126 
00127       image->GetIncrements(inc);
00128       unsigned char *src = (unsigned char *)image->GetScalarPointerForExtent(extent);
00129       unsigned char *dst = *data + planeSize - lineSize;
00130       for (int plane = extent[4]; plane <= extent[5]; plane++)
00131       {
00132          for (int line = extent[2]; line <= extent[3]; line++)
00133          {
00134             // Copy one line at proper destination:
00135             memcpy((void*)dst, (void*)src, lineSize);
00136 
00137             src += inc[1] * image->GetScalarSize();
00138             dst -= lineSize;
00139          }
00140          dst += 2 * planeSize;
00141       }
00142    }
00143    else
00144    {
00145       *data = NULL;
00146    }
00147 
00148    return size;
00149 }
00150 
00154 void SetImageInformation(gdcm::FileHelper *file,vtkImageData *image)
00155 {
00156    std::ostringstream str;
00157 
00158    // Image size
00159    int *extent = image->GetUpdateExtent();
00160    int dim[3] = {extent[1]-extent[0]+1,
00161                  extent[3]-extent[2]+1,
00162                  extent[5]-extent[4]+1};
00163 
00164    str.str("");
00165    str << dim[0];
00166    file->InsertValEntry(str.str(),0x0028,0x0011); // Columns
00167 
00168    str.str("");
00169    str << dim[1];
00170    file->InsertValEntry(str.str(),0x0028,0x0010); // Rows
00171 
00172    if(dim[2]>1)
00173    {
00174       str.str("");
00175       str << dim[2];
00176       //file->Insert(str.str(),0x0028,0x0012); // Planes
00177       file->InsertValEntry(str.str(),0x0028,0x0008); // Number of Frames
00178    }
00179 
00180    // Pixel type
00181    str.str("");
00182    str << image->GetScalarSize()*8;
00183    file->InsertValEntry(str.str(),0x0028,0x0100); // Bits Allocated
00184    file->InsertValEntry(str.str(),0x0028,0x0101); // Bits Stored
00185 
00186    str.str("");
00187    str << image->GetScalarSize()*8-1;
00188    file->InsertValEntry(str.str(),0x0028,0x0102); // High Bit
00189 
00190    // Pixel Repr
00191    // FIXME : what do we do when the ScalarType is 
00192    // VTK_UNSIGNED_INT or VTK_UNSIGNED_LONG
00193    str.str("");
00194    if( image->GetScalarType() == VTK_UNSIGNED_CHAR ||
00195        image->GetScalarType() == VTK_UNSIGNED_SHORT ||
00196        image->GetScalarType() == VTK_UNSIGNED_INT ||
00197        image->GetScalarType() == VTK_UNSIGNED_LONG )
00198    {
00199       str << "0"; // Unsigned
00200    }
00201    else
00202    {
00203       str << "1"; // Signed
00204    }
00205    file->InsertValEntry(str.str(),0x0028,0x0103); // Pixel Representation
00206 
00207    // Samples per pixel
00208    str.str("");
00209    str << image->GetNumberOfScalarComponents();
00210    file->InsertValEntry(str.str(),0x0028,0x0002); // Samples per Pixel
00211 
00212    // Spacing
00213    double *sp = image->GetSpacing();
00214 
00215    str.str("");
00216    str << sp[0] << "\\" << sp[1];
00217    file->InsertValEntry(str.str(),0x0028,0x0030); // Pixel Spacing
00218    str.str("");
00219    str << sp[2];
00220    file->InsertValEntry(str.str(),0x0018,0x0088); // Spacing Between Slices
00221 
00222    // Origin
00223    double *org = image->GetOrigin();
00224 
00225    str.str("");
00226    str << org[0] << "\\" << org[1] << "\\" << org[2];
00227    file->InsertValEntry(str.str(),0x0020,0x0032); // Image Position Patient
00228 
00229    // Window / Level
00230    double *rng=image->GetScalarRange();
00231 
00232    str.str("");
00233    str << rng[1]-rng[0];
00234    file->InsertValEntry(str.str(),0x0028,0x1051); // Window Width
00235    str.str("");
00236    str << (rng[1]+rng[0])/2.0;
00237    file->InsertValEntry(str.str(),0x0028,0x1050); // Window Center
00238 
00239    // Pixels
00240    unsigned char *data;
00241    size_t size = ReverseData(image,&data);
00242    file->SetUserData(data,size);
00243 }
00244 
00249 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *image, ofstream *file)
00250 {
00251    if(file)
00252    {
00253       vtkErrorMacro( <<  "File musn't be opened");
00254       return;
00255    }
00256 
00257    if( image->GetScalarType() == VTK_FLOAT || 
00258        image->GetScalarType() == VTK_DOUBLE )
00259    {
00260       vtkErrorMacro(<< "Bad input type. Scalar type musn't be of type "
00261                     << "VTK_FLOAT or VTKDOUBLE (found:"
00262                     << image->GetScalarTypeAsString());
00263       return;
00264    }
00265 
00266    RecursiveWrite(axis,image,image,file);
00267    //WriteDcmFile(this->FileName,image);
00268 }
00269 
00270 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache, 
00271                                    vtkImageData *image, ofstream *file)
00272 {
00273    int idx, min, max;
00274 
00275    // if the file is already open then just write to it
00276    if( file )
00277    {
00278       vtkErrorMacro( <<  "File musn't be opened");
00279       return;
00280    }
00281 
00282    // if we need to open another slice, do it
00283    if( (axis + 1) == this->FileDimensionality )
00284    {
00285       // determine the name
00286       if (this->FileName)
00287       {
00288          sprintf(this->InternalFileName,"%s",this->FileName);
00289       }
00290       else 
00291       {
00292          if (this->FilePrefix)
00293          {
00294             sprintf(this->InternalFileName, this->FilePattern, 
00295             this->FilePrefix, this->FileNumber);
00296          }
00297          else
00298          {
00299             sprintf(this->InternalFileName, this->FilePattern,this->FileNumber);
00300          }
00301          if (this->FileNumber < this->MinimumFileNumber)
00302          {
00303             this->MinimumFileNumber = this->FileNumber;
00304          }
00305          else if (this->FileNumber > this->MaximumFileNumber)
00306          {
00307             this->MaximumFileNumber = this->FileNumber;
00308          }
00309       }
00310 
00311       // Write the file
00312       WriteDcmFile(this->InternalFileName,image);
00313       ++this->FileNumber;
00314       return;
00315    }
00316 
00317    // if the current region is too high a dimension forthe file
00318    // the we will split the current axis
00319    cache->GetAxisUpdateExtent(axis, min, max);
00320 
00321    // if it is the y axis then flip by default
00322    if (axis == 1 && !this->FileLowerLeft)
00323    {
00324       for(idx = max; idx >= min; idx--)
00325       {
00326          cache->SetAxisUpdateExtent(axis, idx, idx);
00327          this->RecursiveWrite(axis - 1, cache, image, file);
00328       }
00329    }
00330    else
00331    {
00332       for(idx = min; idx <= max; idx++)
00333       {
00334          cache->SetAxisUpdateExtent(axis, idx, idx);
00335          this->RecursiveWrite(axis - 1, cache, image, file);
00336       }
00337    }
00338 
00339    // restore original extent
00340    cache->SetAxisUpdateExtent(axis, min, max);
00341 }
00342 
00343 void vtkGdcmWriter::WriteDcmFile(char *fileName,vtkImageData *image)
00344 {
00345    // From here, the write of the file begins
00346    gdcm::FileHelper *dcmFile = new gdcm::FileHelper();
00347 
00348    // Set the image UID
00349    if( StudyInstanceUID.empty() )
00350       StudyInstanceUID = gdcm::Util::CreateUniqueUID( UIDPrefix );
00351    if( SeriesInstanceUID.empty() )
00352       SeriesInstanceUID = gdcm::Util::CreateUniqueUID( UIDPrefix );
00353    if( FrameOfReferenceInstanceUID.empty() )
00354       FrameOfReferenceInstanceUID = gdcm::Util::CreateUniqueUID( UIDPrefix );
00355    std::string uid = gdcm::Util::CreateUniqueUID( UIDPrefix );
00356 
00357    dcmFile->InsertValEntry(uid,0x0008,0x0018); //[SOP Instance UID]
00358    dcmFile->InsertValEntry(uid,0x0002,0x0003); //[Media Stored SOP Instance UID]
00359    dcmFile->InsertValEntry(StudyInstanceUID,0x0020,0x000d); //[Study Instance UID]
00360    dcmFile->InsertValEntry(SeriesInstanceUID,0x0020,0x000e); //[Series Instance UID]
00361    dcmFile->InsertValEntry(FrameOfReferenceInstanceUID,0x0020, 0x0052); //[Frame of Reference UID] 
00362 
00363    // Set the image informations
00364    SetImageInformation(dcmFile,image);
00365 
00366    // Write the image
00367    switch(this->WriteType)
00368    {
00369       case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
00370          dcmFile->SetWriteTypeToDcmExplVR();
00371          break;
00372       case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
00373          dcmFile->SetWriteTypeToDcmImplVR();
00374          break;
00375       case VTK_GDCM_WRITE_TYPE_ACR :
00376          dcmFile->SetWriteTypeToAcr();
00377          break;
00378       case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
00379          dcmFile->SetWriteTypeToAcrLibido();
00380          break;
00381       default :
00382          dcmFile->SetWriteTypeToDcmExplVR();
00383    }
00384 
00385    if(!dcmFile->Write(fileName))
00386    {
00387       vtkErrorMacro( << "File "  <<  this->FileName  <<  "couldn't be written by "
00388                      << " the gdcm library");
00389    }
00390 
00391    // Clean up
00392    if( dcmFile->GetUserData() && dcmFile->GetUserDataSize()>0 )
00393    {
00394       delete[] dcmFile->GetUserData();
00395    }
00396    delete dcmFile;
00397 }
00398 
00399 //-----------------------------------------------------------------------------
00400 // Private
00401 
00402 //-----------------------------------------------------------------------------

Generated on Thu Feb 10 22:18:01 2005 for gdcm by doxygen 1.3.6