1 /*=========================================================================
4 Module: $RCSfile: vtkGdcmWriter.cxx,v $
6 Date: $Date: 2004/12/10 08:34:08 $
7 Version: $Revision: 1.7 $
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.7 $");
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); // Columns
113 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0010); // Rows
119 //file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0012); // Planes
120 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0008); // Number of Frames
125 str << image->GetScalarSize()*8;
126 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0100); // Bits Allocated
127 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0101); // Bits Stored
130 str << image->GetScalarSize()*8-1;
131 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0102); // High Bit
134 // FIXME : what do we do when the ScalarType is
135 // VTK_UNSIGNED_INT or VTK_UNSIGNED_LONG
137 if( image->GetScalarType() == VTK_UNSIGNED_CHAR ||
138 image->GetScalarType() == VTK_UNSIGNED_SHORT ||
139 image->GetScalarType() == VTK_UNSIGNED_INT ||
140 image->GetScalarType() == VTK_UNSIGNED_LONG )
142 str << "0"; // Unsigned
146 str << "1"; // Signed
148 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0103); // Pixel Representation
152 str << image->GetNumberOfScalarComponents();
153 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0002); // Samples per Pixel
156 double *sp = image->GetSpacing();
159 str << sp[0] << "\\" << sp[1];
160 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x0030); // Pixel Spacing
163 file->ReplaceOrCreateByNumber(str.str(),0x0018,0x0088); // Spacing Between Slices
166 double *org = image->GetOrigin();
169 str << org[0] << "\\" << org[1] << "\\" << org[2];
170 file->ReplaceOrCreateByNumber(str.str(),0x0020,0x0032); // Image Position Patient
173 double *rng=image->GetScalarRange();
176 str << rng[1]-rng[0];
177 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x1051); // Window Width
179 str << (rng[1]+rng[0])/2.0;
180 file->ReplaceOrCreateByNumber(str.str(),0x0028,0x1050); // Window Center
184 size_t size = ReverseData(image,&data);
185 file->SetImageData(data,size);
190 * The call to this method is recursive if there is some files to write
192 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *image, ofstream *file)
196 vtkErrorMacro( << "File musn't be opened");
200 if( image->GetScalarType() == VTK_FLOAT ||
201 image->GetScalarType() == VTK_DOUBLE )
203 vtkErrorMacro(<< "Bad input type. Scalar type musn't be of type "
204 << "VTK_FLOAT or VTKDOUBLE (found:"
205 << image->GetScalarTypeAsString());
209 RecursiveWrite(axis,image,image,file);
210 //WriteDcmFile(this->FileName,image);
213 void vtkGdcmWriter::RecursiveWrite(int axis, vtkImageData *cache,
214 vtkImageData *image, ofstream *file)
218 // if the file is already open then just write to it
221 vtkErrorMacro( << "File musn't be opened");
225 // if we need to open another slice, do it
226 if( (axis + 1) == this->FileDimensionality )
228 // determine the name
231 sprintf(this->InternalFileName,"%s",this->FileName);
235 if (this->FilePrefix)
237 sprintf(this->InternalFileName, this->FilePattern,
238 this->FilePrefix, this->FileNumber);
242 sprintf(this->InternalFileName, this->FilePattern,this->FileNumber);
244 if (this->FileNumber < this->MinimumFileNumber)
246 this->MinimumFileNumber = this->FileNumber;
248 else if (this->FileNumber > this->MaximumFileNumber)
250 this->MaximumFileNumber = this->FileNumber;
255 WriteDcmFile(this->InternalFileName,image);
260 // if the current region is too high a dimension forthe file
261 // the we will split the current axis
262 cache->GetAxisUpdateExtent(axis, min, max);
264 // if it is the y axis then flip by default
265 if (axis == 1 && !this->FileLowerLeft)
267 for(idx = max; idx >= min; idx--)
269 cache->SetAxisUpdateExtent(axis, idx, idx);
270 this->RecursiveWrite(axis - 1, cache, image, file);
275 for(idx = min; idx <= max; idx++)
277 cache->SetAxisUpdateExtent(axis, idx, idx);
278 this->RecursiveWrite(axis - 1, cache, image, file);
282 // restore original extent
283 cache->SetAxisUpdateExtent(axis, min, max);
286 void vtkGdcmWriter::WriteDcmFile(char *fileName,vtkImageData *image)
288 // From here, the write of the file begins
289 gdcm::File *dcmFile = new gdcm::File();
291 // Set the image informations
292 SetImageInformation(dcmFile,image);
295 if(!dcmFile->Write(fileName))
297 vtkErrorMacro( << "File " << this->FileName << "couldn't be written by "
298 << " the gdcm library");
299 std::cerr << "not written \n";
305 //-----------------------------------------------------------------------------
308 //-----------------------------------------------------------------------------