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