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 #ifndef vtkFloatingPointType
00031 #define vtkFloatingPointType float
00032 #endif
00033
00034 vtkCxxRevisionMacro(vtkGdcmWriter, "$Revision: 1.26 $")
00035 vtkStandardNewMacro(vtkGdcmWriter)
00036
00037
00038
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
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
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
00083
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
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
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);
00141
00142 str.str("");
00143 str << dim[1];
00144 file->InsertEntryString(str.str(),0x0028,0x0010);
00145
00146 if(dim[2]>1)
00147 {
00148 str.str("");
00149 str << dim[2];
00150
00151 file->InsertEntryString(str.str(),0x0028,0x0008);
00152 }
00153
00154
00155 str.str("");
00156 str << image->GetScalarSize()*8;
00157 file->InsertEntryString(str.str(),0x0028,0x0100);
00158 file->InsertEntryString(str.str(),0x0028,0x0101);
00159
00160 str.str("");
00161 str << image->GetScalarSize()*8-1;
00162 file->InsertEntryString(str.str(),0x0028,0x0102);
00163
00164
00165
00166
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";
00174 }
00175 else
00176 {
00177 str << "1";
00178 }
00179 file->InsertEntryString(str.str(),0x0028,0x0103);
00180
00181
00182 str.str("");
00183 str << image->GetNumberOfScalarComponents();
00184 file->InsertEntryString(str.str(),0x0028,0x0002);
00185
00188
00189
00190 vtkFloatingPointType *sp = image->GetSpacing();
00191
00192 str.str("");
00193
00194
00195
00196 str.setf( std::ios::fixed );
00197 str << sp[1] << "\\" << sp[0];
00198 file->InsertEntryString(str.str(),0x0028,0x0030);
00199 str.str("");
00200 str << sp[2];
00201 file->InsertEntryString(str.str(),0x0018,0x0088);
00202
00203
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);
00212 str.unsetf( std::ios::fixed );
00213
00214
00215 vtkFloatingPointType *rng = image->GetScalarRange();
00216
00217 str.str("");
00218 str << rng[1]-rng[0];
00219 file->InsertEntryString(str.str(),0x0028,0x1051);
00220 str.str("");
00221 str << (rng[1]+rng[0])/2.0;
00222 file->InsertEntryString(str.str(),0x0028,0x1050);
00223
00224
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
00254 }
00255
00256 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache,
00257 vtkImageData *image, ofstream *file)
00258 {
00259 int idx, min, max;
00260
00261
00262 if( file )
00263 {
00264 vtkErrorMacro( << "File musn't be open");
00265 return;
00266 }
00267
00268
00269 if( (axis + 1) == this->FileDimensionality )
00270 {
00271
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
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
00301 WriteDcmFile(this->InternalFileName,image);
00302 ++this->FileNumber;
00303 return;
00304 }
00305
00306
00307
00308 cache->GetAxisUpdateExtent(axis, min, max);
00309
00310
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
00329 cache->SetAxisUpdateExtent(axis, min, max);
00330 }
00331
00332 void vtkGdcmWriter::WriteDcmFile(char *fileName, vtkImageData *image)
00333 {
00334
00335 gdcm::FileHelper *dcmFile = gdcm::FileHelper::New();
00336
00337
00338 SetImageInformation(dcmFile, image);
00339
00340
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
00366 if( dcmFile->GetUserData() && dcmFile->GetUserDataSize()>0 )
00367 {
00368 delete[] dcmFile->GetUserData();
00369 }
00370 dcmFile->Delete();
00371 }
00372
00373
00374
00375
00376