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
00030 vtkCxxRevisionMacro(vtkGdcmWriter, "$Revision: 1.16 $");
00031 vtkStandardNewMacro(vtkGdcmWriter);
00032
00033
00034
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
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
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
00109
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
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
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);
00167
00168 str.str("");
00169 str << dim[1];
00170 file->InsertValEntry(str.str(),0x0028,0x0010);
00171
00172 if(dim[2]>1)
00173 {
00174 str.str("");
00175 str << dim[2];
00176
00177 file->InsertValEntry(str.str(),0x0028,0x0008);
00178 }
00179
00180
00181 str.str("");
00182 str << image->GetScalarSize()*8;
00183 file->InsertValEntry(str.str(),0x0028,0x0100);
00184 file->InsertValEntry(str.str(),0x0028,0x0101);
00185
00186 str.str("");
00187 str << image->GetScalarSize()*8-1;
00188 file->InsertValEntry(str.str(),0x0028,0x0102);
00189
00190
00191
00192
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";
00200 }
00201 else
00202 {
00203 str << "1";
00204 }
00205 file->InsertValEntry(str.str(),0x0028,0x0103);
00206
00207
00208 str.str("");
00209 str << image->GetNumberOfScalarComponents();
00210 file->InsertValEntry(str.str(),0x0028,0x0002);
00211
00212
00213 double *sp = image->GetSpacing();
00214
00215 str.str("");
00216 str << sp[0] << "\\" << sp[1];
00217 file->InsertValEntry(str.str(),0x0028,0x0030);
00218 str.str("");
00219 str << sp[2];
00220 file->InsertValEntry(str.str(),0x0018,0x0088);
00221
00222
00223 double *org = image->GetOrigin();
00224
00225 str.str("");
00226 str << org[0] << "\\" << org[1] << "\\" << org[2];
00227 file->InsertValEntry(str.str(),0x0020,0x0032);
00228
00229
00230 double *rng=image->GetScalarRange();
00231
00232 str.str("");
00233 str << rng[1]-rng[0];
00234 file->InsertValEntry(str.str(),0x0028,0x1051);
00235 str.str("");
00236 str << (rng[1]+rng[0])/2.0;
00237 file->InsertValEntry(str.str(),0x0028,0x1050);
00238
00239
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
00268 }
00269
00270 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache,
00271 vtkImageData *image, ofstream *file)
00272 {
00273 int idx, min, max;
00274
00275
00276 if( file )
00277 {
00278 vtkErrorMacro( << "File musn't be opened");
00279 return;
00280 }
00281
00282
00283 if( (axis + 1) == this->FileDimensionality )
00284 {
00285
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
00312 WriteDcmFile(this->InternalFileName,image);
00313 ++this->FileNumber;
00314 return;
00315 }
00316
00317
00318
00319 cache->GetAxisUpdateExtent(axis, min, max);
00320
00321
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
00340 cache->SetAxisUpdateExtent(axis, min, max);
00341 }
00342
00343 void vtkGdcmWriter::WriteDcmFile(char *fileName,vtkImageData *image)
00344 {
00345
00346 gdcm::FileHelper *dcmFile = new gdcm::FileHelper();
00347
00348
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);
00358 dcmFile->InsertValEntry(uid,0x0002,0x0003);
00359 dcmFile->InsertValEntry(StudyInstanceUID,0x0020,0x000d);
00360 dcmFile->InsertValEntry(SeriesInstanceUID,0x0020,0x000e);
00361 dcmFile->InsertValEntry(FrameOfReferenceInstanceUID,0x0020, 0x0052);
00362
00363
00364 SetImageInformation(dcmFile,image);
00365
00366
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
00392 if( dcmFile->GetUserData() && dcmFile->GetUserDataSize()>0 )
00393 {
00394 delete[] dcmFile->GetUserData();
00395 }
00396 delete dcmFile;
00397 }
00398
00399
00400
00401
00402