1 /*=========================================================================
4 Module: $RCSfile: vtkGdcmWriter.cxx,v $
6 Date: $Date: 2005/01/20 16:17:01 $
7 Version: $Revision: 1.11 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmHeader.h"
21 #include "gdcmDebug.h"
22 #include "vtkGdcmWriter.h"
24 #include <vtkObjectFactory.h>
25 #include <vtkImageData.h>
26 #include <vtkPointData.h>
27 #include <vtkLookupTable.h>
29 vtkCxxRevisionMacro(vtkGdcmWriter, "$Revision: 1.11 $");
30 vtkStandardNewMacro(vtkGdcmWriter);
32 //-----------------------------------------------------------------------------
33 // Constructor / Destructor
34 vtkGdcmWriter::vtkGdcmWriter()
36 this->LookupTable = NULL;
37 this->FileDimensionality = 3;
38 this->WriteType = VTK_GDCM_WRITE_TYPE_EXPLICIT_VR;
41 vtkGdcmWriter::~vtkGdcmWriter()
45 //-----------------------------------------------------------------------------
47 void vtkGdcmWriter::PrintSelf(ostream& os, vtkIndent indent)
49 this->Superclass::PrintSelf(os,indent);
51 os << indent << "Write type : " << this->GetWriteTypeAsString();
54 //-----------------------------------------------------------------------------
56 const char *vtkGdcmWriter::GetWriteTypeAsString()
60 case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
62 case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
64 case VTK_GDCM_WRITE_TYPE_ACR :
66 case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
73 //-----------------------------------------------------------------------------
76 * Copy the image and reverse the Y axis
78 // The output datas must be deleted by the user of the method !!!
79 size_t ReverseData(vtkImageData *image,unsigned char **data)
82 int *extent = image->GetUpdateExtent();
83 int dim[3] = {extent[1]-extent[0]+1,
84 extent[3]-extent[2]+1,
85 extent[5]-extent[4]+1};
87 size_t lineSize = dim[0] * image->GetScalarSize()
88 * image->GetNumberOfScalarComponents();
89 size_t planeSize = dim[1] * lineSize;
90 size_t size = dim[2] * planeSize;
94 *data = new unsigned char[size];
96 image->GetIncrements(inc);
97 unsigned char *src = (unsigned char *)image->GetScalarPointerForExtent(extent);
98 unsigned char *dst = *data + planeSize - lineSize;
99 for (int plane = extent[4]; plane <= extent[5]; plane++)
101 for (int line = extent[2]; line <= extent[3]; line++)
103 // Copy one line at proper destination:
104 memcpy((void*)dst, (void*)src, lineSize);
106 src += inc[1] * image->GetScalarSize();
109 dst += 2 * planeSize;
121 * Set the datas informations in the file
123 void SetImageInformation(gdcm::FileHelper *file,vtkImageData *image)
125 std::ostringstream str;
128 int *extent = image->GetUpdateExtent();
129 int dim[3] = {extent[1]-extent[0]+1,
130 extent[3]-extent[2]+1,
131 extent[5]-extent[4]+1};
135 file->ReplaceOrCreate(str.str(),0x0028,0x0011); // Columns
139 file->ReplaceOrCreate(str.str(),0x0028,0x0010); // Rows
145 //file->ReplaceOrCreate(str.str(),0x0028,0x0012); // Planes
146 file->ReplaceOrCreate(str.str(),0x0028,0x0008); // Number of Frames
151 str << image->GetScalarSize()*8;
152 file->ReplaceOrCreate(str.str(),0x0028,0x0100); // Bits Allocated
153 file->ReplaceOrCreate(str.str(),0x0028,0x0101); // Bits Stored
156 str << image->GetScalarSize()*8-1;
157 file->ReplaceOrCreate(str.str(),0x0028,0x0102); // High Bit
160 // FIXME : what do we do when the ScalarType is
161 // VTK_UNSIGNED_INT or VTK_UNSIGNED_LONG
163 if( image->GetScalarType() == VTK_UNSIGNED_CHAR ||
164 image->GetScalarType() == VTK_UNSIGNED_SHORT ||
165 image->GetScalarType() == VTK_UNSIGNED_INT ||
166 image->GetScalarType() == VTK_UNSIGNED_LONG )
168 str << "0"; // Unsigned
172 str << "1"; // Signed
174 file->ReplaceOrCreate(str.str(),0x0028,0x0103); // Pixel Representation
178 str << image->GetNumberOfScalarComponents();
179 file->ReplaceOrCreate(str.str(),0x0028,0x0002); // Samples per Pixel
182 double *sp = image->GetSpacing();
185 str << sp[0] << "\\" << sp[1];
186 file->ReplaceOrCreate(str.str(),0x0028,0x0030); // Pixel Spacing
189 file->ReplaceOrCreate(str.str(),0x0018,0x0088); // Spacing Between Slices
192 double *org = image->GetOrigin();
195 str << org[0] << "\\" << org[1] << "\\" << org[2];
196 file->ReplaceOrCreate(str.str(),0x0020,0x0032); // Image Position Patient
199 double *rng=image->GetScalarRange();
202 str << rng[1]-rng[0];
203 file->ReplaceOrCreate(str.str(),0x0028,0x1051); // Window Width
205 str << (rng[1]+rng[0])/2.0;
206 file->ReplaceOrCreate(str.str(),0x0028,0x1050); // Window Center
210 size_t size = ReverseData(image,&data);
211 file->SetUserData(data,size);
216 * The call to this method is recursive if there is some files to write
218 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *image, ofstream *file)
222 vtkErrorMacro( << "File musn't be opened");
226 if( image->GetScalarType() == VTK_FLOAT ||
227 image->GetScalarType() == VTK_DOUBLE )
229 vtkErrorMacro(<< "Bad input type. Scalar type musn't be of type "
230 << "VTK_FLOAT or VTKDOUBLE (found:"
231 << image->GetScalarTypeAsString());
235 RecursiveWrite(axis,image,image,file);
236 //WriteDcmFile(this->FileName,image);
239 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache,
240 vtkImageData *image, ofstream *file)
244 // if the file is already open then just write to it
247 vtkErrorMacro( << "File musn't be opened");
251 // if we need to open another slice, do it
252 if( (axis + 1) == this->FileDimensionality )
254 // determine the name
257 sprintf(this->InternalFileName,"%s",this->FileName);
261 if (this->FilePrefix)
263 sprintf(this->InternalFileName, this->FilePattern,
264 this->FilePrefix, this->FileNumber);
268 sprintf(this->InternalFileName, this->FilePattern,this->FileNumber);
270 if (this->FileNumber < this->MinimumFileNumber)
272 this->MinimumFileNumber = this->FileNumber;
274 else if (this->FileNumber > this->MaximumFileNumber)
276 this->MaximumFileNumber = this->FileNumber;
281 WriteDcmFile(this->InternalFileName,image);
286 // if the current region is too high a dimension forthe file
287 // the we will split the current axis
288 cache->GetAxisUpdateExtent(axis, min, max);
290 // if it is the y axis then flip by default
291 if (axis == 1 && !this->FileLowerLeft)
293 for(idx = max; idx >= min; idx--)
295 cache->SetAxisUpdateExtent(axis, idx, idx);
296 this->RecursiveWrite(axis - 1, cache, image, file);
301 for(idx = min; idx <= max; idx++)
303 cache->SetAxisUpdateExtent(axis, idx, idx);
304 this->RecursiveWrite(axis - 1, cache, image, file);
308 // restore original extent
309 cache->SetAxisUpdateExtent(axis, min, max);
312 void vtkGdcmWriter::WriteDcmFile(char *fileName,vtkImageData *image)
314 // From here, the write of the file begins
315 gdcm::FileHelper *dcmFile = new gdcm::FileHelper();
317 // Set the image informations
318 SetImageInformation(dcmFile,image);
321 switch(this->WriteType)
323 case VTK_GDCM_WRITE_TYPE_EXPLICIT_VR :
324 dcmFile->SetWriteTypeToDcmExplVR();
326 case VTK_GDCM_WRITE_TYPE_IMPLICIT_VR :
327 dcmFile->SetWriteTypeToDcmImplVR();
329 case VTK_GDCM_WRITE_TYPE_ACR :
330 dcmFile->SetWriteTypeToAcr();
332 case VTK_GDCM_WRITE_TYPE_ACR_LIBIDO :
333 dcmFile->SetWriteTypeToAcrLibido();
336 dcmFile->SetWriteTypeToDcmExplVR();
339 if(!dcmFile->Write(fileName))
341 vtkErrorMacro( << "File " << this->FileName << "couldn't be written by "
342 << " the gdcm library");
346 if( dcmFile->GetUserData() && dcmFile->GetUserDataSize()>0 )
348 delete[] dcmFile->GetUserData();
353 //-----------------------------------------------------------------------------
356 //-----------------------------------------------------------------------------