1 /*=========================================================================
4 Module: $RCSfile: vtkGdcmWriter.cxx,v $
6 Date: $Date: 2004/12/09 17:08:36 $
7 Version: $Revision: 1.6 $
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.6 $");
30 vtkStandardNewMacro(vtkGdcmWriter);
32 //-----------------------------------------------------------------------------
33 // Constructor / Destructor
34 vtkGdcmWriter::vtkGdcmWriter()
36 this->LookupTable = NULL;
37 this->FileDimensionality = 3;
40 vtkGdcmWriter::~vtkGdcmWriter()
44 //-----------------------------------------------------------------------------
46 void vtkGdcmWriter::PrintSelf(ostream& os, vtkIndent indent)
48 this->Superclass::PrintSelf(os,indent);
51 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
57 * Copy the image and reverse the Y axis
59 // The output datas must be deleted by the user of the method !!!
60 size_t ReverseData(vtkImageData *image,unsigned char **data)
63 int *extent = image->GetUpdateExtent();
64 int dim[3] = {extent[1]-extent[0]+1,
65 extent[3]-extent[2]+1,
66 extent[5]-extent[4]+1};
68 size_t lineSize = dim[0] * image->GetScalarSize()
69 * image->GetNumberOfScalarComponents();
70 size_t planeSize = dim[1] * lineSize;
71 size_t size = dim[2] * planeSize;
73 *data = new unsigned char[size];
75 image->GetIncrements(inc);
76 unsigned char *src = (unsigned char *)image->GetScalarPointerForExtent(extent);
77 unsigned char *dst = *data + planeSize - lineSize;
78 for (int plane = extent[4]; plane <= extent[5]; plane++)
80 for (int line = extent[2]; line <= extent[3]; line++)
82 // Copy one line at proper destination:
83 memcpy((void*)dst, (void*)src, lineSize);
85 src += inc[1]*image->GetScalarSize();
95 * Set the datas informations in the file
97 void SetImageInformation(gdcm::File *file,vtkImageData *image)
99 std::ostringstream str;
102 int *extent = image->GetUpdateExtent();
103 int dim[3] = {extent[1]-extent[0]+1,
104 extent[3]-extent[2]+1,
105 extent[5]-extent[4]+1};
109 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0011);
113 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0010);
119 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0012);
124 str << image->GetScalarSize()*8;
125 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0100);
126 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0101);
129 str << image->GetScalarSize()*8-1;
130 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0102);
133 // FIXME : what do we do when the ScalarType is
134 // VTK_UNSIGNED_INT or VTK_UNSIGNED_LONG
136 if( image->GetScalarType() == VTK_UNSIGNED_CHAR ||
137 image->GetScalarType() == VTK_UNSIGNED_SHORT ||
138 image->GetScalarType() == VTK_UNSIGNED_INT ||
139 image->GetScalarType() == VTK_UNSIGNED_LONG )
141 str << "0"; // Unsigned
145 str << "1"; // Signed
147 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0103);
151 str << image->GetNumberOfScalarComponents();
152 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0002);
155 double *sp = image->GetSpacing();
158 str << sp[0] << "\\" << sp[1];
159 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0030);
162 file->ReplaceOrCreateByNumber(str.str(),0x0018,0x0088);
165 double *org = image->GetOrigin();
168 str << org[0] << "\\" << org[1] << "\\" << org[2];
169 file->ReplaceOrCreateByNumber(str.str(),0x0020,0x0032);
172 double *rng=image->GetScalarRange();
175 str << rng[1]-rng[0];
176 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x1051);
178 str << (rng[1]+rng[0])/2.0;
179 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x1050);
183 size_t size = ReverseData(image,&data);
184 file->SetImageData(data,size);
189 * The call to this method is recursive if there is some files to write
191 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *image, ofstream *file)
195 vtkErrorMacro( << "File musn't be opened");
199 if( image->GetScalarType() == VTK_FLOAT ||
200 image->GetScalarType() == VTK_DOUBLE )
202 vtkErrorMacro(<< "Bad input type. Scalar type musn't be of type "
203 << "VTK_FLOAT or VTKDOUBLE (found:"
204 << image->GetScalarTypeAsString());
208 RecursiveWrite(axis,image,image,file);
209 //WriteDcmFile(this->FileName,image);
212 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache,
213 vtkImageData *image, ofstream *file)
217 // if the file is already open then just write to it
220 vtkErrorMacro( << "File musn't be opened");
224 // if we need to open another slice, do it
225 if( (axis + 1) == this->FileDimensionality )
227 // determine the name
230 sprintf(this->InternalFileName,"%s",this->FileName);
234 if (this->FilePrefix)
236 sprintf(this->InternalFileName, this->FilePattern,
237 this->FilePrefix, this->FileNumber);
241 sprintf(this->InternalFileName, this->FilePattern,this->FileNumber);
243 if (this->FileNumber < this->MinimumFileNumber)
245 this->MinimumFileNumber = this->FileNumber;
247 else if (this->FileNumber > this->MaximumFileNumber)
249 this->MaximumFileNumber = this->FileNumber;
254 WriteDcmFile(this->InternalFileName,image);
259 // if the current region is too high a dimension forthe file
260 // the we will split the current axis
261 cache->GetAxisUpdateExtent(axis, min, max);
263 // if it is the y axis then flip by default
264 if (axis == 1 && !this->FileLowerLeft)
266 for(idx = max; idx >= min; idx--)
268 cache->SetAxisUpdateExtent(axis, idx, idx);
269 this->RecursiveWrite(axis - 1, cache, image, file);
274 for(idx = min; idx <= max; idx++)
276 cache->SetAxisUpdateExtent(axis, idx, idx);
277 this->RecursiveWrite(axis - 1, cache, image, file);
281 // restore original extent
282 cache->SetAxisUpdateExtent(axis, min, max);
285 void vtkGdcmWriter::WriteDcmFile(char *fileName,vtkImageData *image)
287 // From here, the write of the file begins
288 gdcm::File *dcmFile = new gdcm::File();
290 // Set the image informations
291 SetImageInformation(dcmFile,image);
294 if(!dcmFile->Write(fileName))
296 vtkErrorMacro( << "File " << this->FileName << "couldn't be written by "
297 << " the gdcm library");
298 std::cerr << "not written \n";
304 //-----------------------------------------------------------------------------
307 //-----------------------------------------------------------------------------