1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
20 #include "clitkDicomRTDoseIO.h"
21 #include "clitkCommon.h"
24 #include <gdcmFileHelper.h>
26 #define GFOV_SPACING_TOL (1e-1)
28 //--------------------------------------------------------------------
29 // Read Image Information
30 void clitk::DicomRTDoseIO::ReadImageInformation()
34 m_GdcmFile = new gdcm::File;
41 float *gfov; /* gfov = GridFrameOffsetVector */
45 m_GdcmFile->SetMaxSizeLoadEntry (0xffff);
46 m_GdcmFile->SetFileName (m_FileName.c_str());
47 m_GdcmFile->SetLoadMode (0);
50 /* Modality -- better be RTSTRUCT */
51 tmp = m_GdcmFile->GetEntryValue (0x0008, 0x0060);
52 if (strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) {
53 itkExceptionMacro(<< "Error. Input file not RTDOSE: " << m_FileName);
56 /* ImagePositionPatient */
57 tmp = m_GdcmFile->GetEntryValue (0x0020, 0x0032);
58 rc = sscanf (tmp.c_str(), "%f\\%f\\%f", &ipp[0], &ipp[1], &ipp[2]);
60 itkExceptionMacro(<< "Error parsing RTDOSE ipp.");
64 tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0010);
65 rc = sscanf (tmp.c_str(), "%d", &dim[1]);
67 itkExceptionMacro(<< "Error parsing RTDOSE rows.");
71 tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0011);
72 rc = sscanf (tmp.c_str(), "%d", &dim[0]);
74 itkExceptionMacro(<< "Error parsing RTDOSE columns.");
78 tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0030);
79 rc = sscanf (tmp.c_str(), "%g\\%g", &spacing[0], &spacing[1]);
82 itkExceptionMacro(<< "Error parsing RTDOSE pixel spacing.");
85 /* GridFrameOffsetVector */
86 tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000C);
89 gfov_str = tmp.c_str();
92 gfov = (float*) realloc (gfov, (gfov_len + 1) * sizeof(float));
93 rc = sscanf (gfov_str, "%g%n", &gfov[gfov_len], &len);
99 if (gfov_str[0] == '\\') {
105 itkExceptionMacro(<< "Error parsing RTDOSE gfov.");
108 /* --- Analyze GridFrameOffsetVector --- */
110 /* (1) Make sure first element is 0. */
112 itkExceptionMacro(<< "Error RTDOSE gfov[0] is not 0.");
115 /* (2) Handle case where gfov_len == 1 (only one slice). */
117 spacing[2] = spacing[0];
120 /* (3) Check to make sure spacing is regular. */
121 for (i = 1; i < gfov_len; i++) {
123 spacing[2] = gfov[1] - gfov[0];
125 float sp = gfov[i] - gfov[i-1];
126 if (fabs(sp - spacing[2]) > GFOV_SPACING_TOL) {
127 itkExceptionMacro(<< "Error RTDOSE grid has irregular spacing:"
128 << sp << " vs " << spacing[2]);
135 /* DoseGridScaling */
137 tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000E);
138 rc = sscanf (tmp.c_str(), "%f", &m_DoseScaling);
139 /* If element doesn't exist, scaling is 1.0 */
141 // set dimension values
142 SetNumberOfDimensions(3);
143 for(int i=0; i<3; i++) {
144 SetDimensions(i, dim[i]);
145 SetSpacing(i, spacing[i]);
146 SetOrigin(i, ipp[i]);
149 // set other information
150 SetByteOrderToLittleEndian();
151 SetPixelType(itk::ImageIOBase::SCALAR);
152 SetNumberOfComponents(1);
153 SetComponentType(itk::ImageIOBase::FLOAT);
156 //--------------------------------------------------------------------
157 // Read Image Information
158 bool clitk::DicomRTDoseIO::CanReadFile(const char* FileNameToRead)
160 // opening dicom input file
162 dcmFile.SetFileName(FileNameToRead);
163 if (!dcmFile.OpenFile())
166 //Taken from plastimatch
167 dcmFile.SetMaxSizeLoadEntry (0xffff);
168 dcmFile.SetLoadMode (0);
171 /* Modality -- better be RTDOSE */
172 std::string tmp = dcmFile.GetEntryValue (0x0008, 0x0060);
173 if (!strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) {
180 //--------------------------------------------------------------------
183 clitk::DicomRTDoseIO::dose_copy_raw (float *img_out, T *img_in, int nvox, float scale)
185 for (int i = 0; i < nvox; i++) {
186 img_out[i] = img_in[i] * scale;
190 //--------------------------------------------------------------------
191 // Read Image Content
192 void clitk::DicomRTDoseIO::Read(void * buffer)
194 float *img = (float*) buffer;
196 unsigned long npix = 1;
197 for(unsigned int i=0; i<GetNumberOfDimensions(); i++)
198 npix *= GetDimensions(i);
201 gdcm::FileHelper m_GdcmFile_helper (m_GdcmFile);
203 //size_t image_data_size = m_GdcmFile_helper.GetImageDataSize();
204 if (strcmp (m_GdcmFile->GetPixelType().c_str(), "16U")==0) {
205 unsigned short* image_data = (unsigned short*) m_GdcmFile_helper.GetImageData();
206 dose_copy_raw (img, image_data, npix, m_DoseScaling);
207 } else if (strcmp(m_GdcmFile->GetPixelType().c_str(),"32U")==0) {
208 unsigned long* image_data = (unsigned long*) m_GdcmFile_helper.GetImageData ();
209 dose_copy_raw (img, image_data, npix, m_DoseScaling);
211 itkExceptionMacro(<< "Error RTDOSE not type 16U and 32U (type="
212 << m_GdcmFile->GetPixelType().c_str() << ")");
215 /* GCS FIX: Do I need to do something about endian-ness? */
219 /* Copy data to volume */
220 // float *img = (float*) vol->img;
221 // for (i = 0; i < vol->npix; i++) {
222 //img[i] = image_data[i] * m_DoseScaling;
228 //--------------------------------------------------------------------
229 // Write Image Information
230 void clitk::DicomRTDoseIO::WriteImageInformation(bool keepOfStream)
234 //--------------------------------------------------------------------
235 // Write Image Information
236 bool clitk::DicomRTDoseIO::CanWriteFile(const char* FileNameToWrite)
241 //--------------------------------------------------------------------
243 void clitk::DicomRTDoseIO::Write(const void * buffer)