00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
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 #if (VTK_MAJOR_VERSION >= 5)
00030 #include <vtkMedicalImageProperties.h>
00031 #endif
00032 #ifndef vtkFloatingPointType
00033 #define vtkFloatingPointType float
00034 #endif
00035 
00036 vtkCxxRevisionMacro(vtkGdcmWriter, "$Revision: 1.34 $")
00037 vtkStandardNewMacro(vtkGdcmWriter)
00038 
00039 vtkCxxSetObjectMacro(vtkGdcmWriter,LookupTable,vtkLookupTable);
00040 #if (VTK_MAJOR_VERSION >= 5)
00041 vtkCxxSetObjectMacro(vtkGdcmWriter,MedicalImageProperties,vtkMedicalImageProperties);
00042 #endif
00043 
00044 
00045 vtkGdcmWriter::vtkGdcmWriter()
00046 {
00047    this->LookupTable = NULL;
00048    this->MedicalImageProperties = NULL;
00049    this->FileDimensionality = 3;
00050    this->WriteType = VTK_GDCM_WRITE_TYPE_EXPLICIT_VR;
00051    this->GdcmFile = 0;
00052    this->ContentType = VTK_GDCM_WRITE_TYPE_USER_OWN_IMAGE;
00053 }
00054 
00055 vtkGdcmWriter::~vtkGdcmWriter()
00056 {
00057    this->SetMedicalImageProperties(NULL);
00058    this->SetLookupTable(NULL);
00059 }
00060 
00061 
00062 
00063 void vtkGdcmWriter::PrintSelf(ostream &os, vtkIndent indent)
00064 {
00065    this->Superclass::PrintSelf(os, indent);
00066 
00067    os << indent << "Write type : " << this->GetWriteTypeAsString();
00068 }
00069 
00070 
00071 
00072 const char *vtkGdcmWriter::GetWriteTypeAsString()
00073 {
00074    switch(WriteType)
00075    {
00076       case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
00077          return "Explicit VR";
00078       case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
00079          return "Implicit VR";
00080       case VTK_GDCM_WRITE_TYPE_ACR :
00081          return "ACR";
00082       case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
00083          return "ACR Libido";
00084       default :
00085          return "Unknow type";
00086    }
00087 }
00088 
00089 
00090 
00094 
00095 size_t ReverseData(vtkImageData *image,unsigned char **data)
00096 {
00097 #if (VTK_MAJOR_VERSION >= 5)
00098    vtkIdType inc[3];
00099 #else
00100    int inc[3];
00101 #endif
00102    int *extent = image->GetUpdateExtent();
00103    int dim[3] = {extent[1]-extent[0]+1,
00104                  extent[3]-extent[2]+1,
00105                  extent[5]-extent[4]+1};
00106 
00107    size_t lineSize = dim[0] * image->GetScalarSize()
00108                    * image->GetNumberOfScalarComponents();
00109    size_t planeSize = dim[1] * lineSize;
00110    size_t size = dim[2] * planeSize;
00111 
00112    if( size>0 )
00113    {
00114       *data = new unsigned char[size];
00115 
00116       image->GetIncrements(inc);
00117       unsigned char *src = (unsigned char *)image->GetScalarPointerForExtent(extent);
00118       unsigned char *dst = *data + planeSize - lineSize;
00119       for (int plane = extent[4]; plane <= extent[5]; plane++)
00120       {
00121          for (int line = extent[2]; line <= extent[3]; line++)
00122          {
00123             
00124             memcpy((void*)dst, (void*)src, lineSize);
00125 
00126             src += inc[1] * image->GetScalarSize();
00127             dst -= lineSize;
00128          }
00129          dst += 2 * planeSize;
00130       }
00131    }
00132    else
00133    {
00134       *data = NULL;
00135    }
00136 
00137    return size;
00138 }
00139 
00144 #if (VTK_MAJOR_VERSION >= 5)
00145 void SetMedicalImageInformation(GDCM_NAME_SPACE::FileHelper *file, vtkMedicalImageProperties *medprop)
00146 {
00147    
00148    
00149    std::ostringstream str;
00150    if( medprop )
00151      {
00152      if (medprop->GetPatientName())
00153         {
00154         str.str("");
00155         str << medprop->GetPatientName();
00156         file->InsertEntryString(str.str(),0x0010,0x0010,"PN"); 
00157         }
00158 
00159      if (medprop->GetPatientID())
00160         {
00161         str.str("");
00162         str << medprop->GetPatientID();
00163         file->InsertEntryString(str.str(),0x0010,0x0020,"LO"); 
00164         }
00165 
00166      if (medprop->GetPatientAge())
00167         {
00168         str.str("");
00169         str << medprop->GetPatientAge();
00170         file->InsertEntryString(str.str(),0x0010,0x1010,"AS"); 
00171         }
00172 
00173      if (medprop->GetPatientSex())
00174         {
00175         str.str("");
00176         str << medprop->GetPatientSex();
00177         file->InsertEntryString(str.str(),0x0010,0x0040,"CS"); 
00178         }
00179 
00180      if (medprop->GetPatientBirthDate())
00181         {
00182         str.str("");
00183         str << medprop->GetPatientBirthDate();
00184         file->InsertEntryString(str.str(),0x0010,0x0030,"DA"); 
00185         }
00186 
00187      if (medprop->GetStudyID())
00188         {
00189         str.str("");
00190         str << medprop->GetStudyID();
00191         file->InsertEntryString(str.str(),0x0020,0x0010,"SH"); 
00192         }
00193      }
00194 }
00195 #endif
00196 
00200 void SetImageInformation(GDCM_NAME_SPACE::FileHelper *file, vtkImageData *image)
00201 {
00202    std::ostringstream str;
00203 
00204    
00205    int *extent = image->GetUpdateExtent();
00206    int dim[3] = {extent[1]-extent[0]+1,
00207                  extent[3]-extent[2]+1,
00208                  extent[5]-extent[4]+1};
00209 
00210    str.str("");
00211    str << dim[0];
00212    file->InsertEntryString(str.str(),0x0028,0x0011,"US"); 
00213 
00214    str.str("");
00215    str << dim[1];
00216    file->InsertEntryString(str.str(),0x0028,0x0010,"US"); 
00217 
00218    if(dim[2]>1)
00219    {
00220       str.str("");
00221       str << dim[2];
00222       
00223       file->InsertEntryString(str.str(),0x0028,0x0008,"US"); 
00224    }
00225 
00226    
00227    str.str("");
00228    str << image->GetScalarSize()*8;
00229    file->InsertEntryString(str.str(),0x0028,0x0100,"US"); 
00230    file->InsertEntryString(str.str(),0x0028,0x0101,"US"); 
00231 
00232    str.str("");
00233    str << image->GetScalarSize()*8-1;
00234    file->InsertEntryString(str.str(),0x0028,0x0102,"US"); 
00235 
00236    
00237    
00238    
00239    str.str("");
00240    if( image->GetScalarType() == VTK_UNSIGNED_CHAR  ||
00241        image->GetScalarType() == VTK_UNSIGNED_SHORT ||
00242        image->GetScalarType() == VTK_UNSIGNED_INT   ||
00243        image->GetScalarType() == VTK_UNSIGNED_LONG )
00244    {
00245       str << "0"; 
00246    }
00247    else
00248    {
00249       str << "1"; 
00250    }
00251    file->InsertEntryString(str.str(),0x0028,0x0103,"US"); 
00252 
00253    
00254    str.str("");
00255    str << image->GetNumberOfScalarComponents();
00256    file->InsertEntryString(str.str(),0x0028,0x0002,"US"); 
00257 
00260 
00261    
00262    vtkFloatingPointType *sp = image->GetSpacing();
00263 
00264    str.str("");
00265    
00266    
00267    
00268    str.setf( std::ios::fixed );
00269    str << sp[1] << "\\" << sp[0];
00270    file->InsertEntryString(str.str(),0x0028,0x0030,"DS"); 
00271    str.str("");
00272    str << sp[2];
00273    file->InsertEntryString(str.str(),0x0018,0x0088,"DS"); 
00274 
00275    
00276    vtkFloatingPointType *org = image->GetOrigin();
00277 
00280 
00281    str.str("");
00282    str << org[0] << "\\" << org[1] << "\\" << org[2];
00283    file->InsertEntryString(str.str(),0x0020,0x0032,"DS"); 
00284    str.unsetf( std::ios::fixed ); 
00285 
00286    
00287    vtkFloatingPointType *rng = image->GetScalarRange();
00288 
00289    str.str("");
00290    str << rng[1]-rng[0];
00291    file->InsertEntryString(str.str(),0x0028,0x1051,"DS"); 
00292    str.str("");
00293    str << (rng[1]+rng[0])/2.0;
00294    file->InsertEntryString(str.str(),0x0028,0x1050,"DS"); 
00295 
00296    
00297    unsigned char *data;
00298    size_t size = ReverseData(image,&data);
00299    file->SetUserData(data,size);
00300 }
00301 
00306 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *image, 
00307                     ofstream *file)
00308 {
00309    if(file)
00310    {
00311       vtkErrorMacro( <<  "File must not be open");
00312       return;
00313    }
00314 
00315    if( image->GetScalarType() == VTK_FLOAT || 
00316        image->GetScalarType() == VTK_DOUBLE )
00317    {
00318       vtkErrorMacro(<< "Bad input type. Scalar type must not be of type "
00319                     << "VTK_FLOAT or VTK_DOUBLE (found:"
00320                     << image->GetScalarTypeAsString() << ")" );
00321       return;
00322    }
00323 
00324    RecursiveWrite(axis,image, image, file);
00325    
00326 }
00327 
00328 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache, 
00329                                    vtkImageData *image, ofstream *file)
00330 {
00331    int idx, min, max;
00332 
00333    
00334    if( file )
00335    {
00336       vtkErrorMacro( <<  "File musn't be open");
00337       return;
00338    }
00339 
00340    
00341    if( (axis + 1) == this->FileDimensionality )
00342    {
00343       
00344       if (this->FileName)
00345       {
00346          sprintf(this->InternalFileName, "%s", this->FileName);
00347       }
00348       else 
00349       {
00350          if (this->FilePrefix)
00351          {
00352             sprintf(this->InternalFileName, this->FilePattern, 
00353             this->FilePrefix, this->FileNumber);
00354          }
00355          else
00356          {
00357             sprintf(this->InternalFileName, this->FilePattern,this->FileNumber);
00358          }
00359 
00360 #if !(VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION == 2)
00361          if (this->FileNumber < this->MinimumFileNumber)
00362          {
00363             this->MinimumFileNumber = this->FileNumber;
00364          }
00365          else if (this->FileNumber > this->MaximumFileNumber)
00366          {
00367             this->MaximumFileNumber = this->FileNumber;
00368          }
00369 #endif
00370       }
00371 
00372       
00373       WriteDcmFile(this->InternalFileName,image);
00374       ++this->FileNumber;
00375       return;
00376    }
00377 
00378    
00379    
00380    cache->GetAxisUpdateExtent(axis, min, max);
00381 
00382    
00383    if (axis == 1 && !this->FileLowerLeft)
00384    {
00385       for(idx = max; idx >= min; idx--)
00386       {
00387          cache->SetAxisUpdateExtent(axis, idx, idx);
00388          this->RecursiveWrite(axis - 1, cache, image, file);
00389       }
00390    }
00391    else
00392    {
00393       for(idx = min; idx <= max; idx++)
00394       {
00395          cache->SetAxisUpdateExtent(axis, idx, idx);
00396          this->RecursiveWrite(axis - 1, cache, image, file);
00397       }
00398    }
00399 
00400    
00401    cache->SetAxisUpdateExtent(axis, min, max);
00402 }
00403 
00404 void vtkGdcmWriter::WriteDcmFile(char *fileName, vtkImageData *image)
00405 {
00406    GDCM_NAME_SPACE::FileHelper *dcmFile;
00407    if ( GdcmFile != 0)
00408       dcmFile = GDCM_NAME_SPACE::FileHelper::New(GdcmFile);
00409    else
00410       dcmFile = GDCM_NAME_SPACE::FileHelper::New();
00411    
00412    
00413 
00414    
00415 #if (VTK_MAJOR_VERSION >= 5)  
00416    SetMedicalImageInformation(dcmFile, this->MedicalImageProperties);
00417 #endif
00418       
00419    
00420    SetImageInformation(dcmFile, image);
00421 
00422    
00423    switch(this->WriteType)
00424    {
00425       case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
00426          dcmFile->SetWriteTypeToDcmExplVR();
00427          break;
00428       case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
00429          dcmFile->SetWriteTypeToDcmImplVR();
00430          break;
00431       case VTK_GDCM_WRITE_TYPE_ACR :
00432          dcmFile->SetWriteTypeToAcr();
00433          break;
00434       case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
00435          dcmFile->SetWriteTypeToAcrLibido();
00436          break;
00437       default :
00438          dcmFile->SetWriteTypeToDcmExplVR();
00439    }
00440   
00441    dcmFile->SetContentType((GDCM_NAME_SPACE::ImageContentType)ContentType);
00442  
00443    if(!dcmFile->Write(fileName))
00444    {
00445       vtkErrorMacro( << "File "  <<  this->FileName  <<  "cannot be written by "
00446                      << " the gdcm library");
00447    }
00448    
00449    if( dcmFile->GetUserData() && dcmFile->GetUserDataSize()>0 )
00450    {
00451       delete[] dcmFile->GetUserData();
00452    }
00453    dcmFile->Delete();
00454 }
00455 
00456 
00457 
00458 
00459