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 #if GDCM_MAJOR_VERSION == 2
25 #include <gdcmReader.h>
26 #include <gdcmAttribute.h>
28 #include <gdcmFileHelper.h>
31 #define GFOV_SPACING_TOL (1e-1)
33 //--------------------------------------------------------------------
34 // Read Image Information
35 void clitk::DicomRTDoseIO::ReadImageInformation()
37 #if GDCM_MAJOR_VERSION < 2
40 m_GdcmFile = new gdcm::File;
48 double *gfov; /* gfov = GridFrameOffsetVector */
50 #if GDCM_MAJOR_VERSION < 2
55 #if GDCM_MAJOR_VERSION == 2
56 m_GdcmImageReader.SetFileName(m_FileName.c_str());
57 m_GdcmImageReader.Read();
58 gdcm::File* m_GdcmFile = &m_GdcmImageReader.GetFile();
60 m_GdcmFile->SetMaxSizeLoadEntry (0xffff);
61 m_GdcmFile->SetFileName (m_FileName.c_str());
62 m_GdcmFile->SetLoadMode (0);
66 /* Modality -- better be RTSTRUCT */
67 #if GDCM_MAJOR_VERSION == 2
68 gdcm::DataSet &ds = m_GdcmFile->GetDataSet();
70 gdcm::Attribute<0x8,0x60> at1;
71 at1.SetFromDataSet(ds);
74 tmp = m_GdcmFile->GetEntryValue (0x0008, 0x0060);
76 if (strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) {
77 itkExceptionMacro(<< "Error. Input file not RTDOSE: " << m_FileName);
80 /* ImagePositionPatient */
81 #if GDCM_MAJOR_VERSION == 2
82 gdcm::Attribute<0x20,0x32> at2;
83 at2.SetFromDataSet(ds);
84 ipp[0] = at2.GetValue(0);
85 ipp[1] = at2.GetValue(1);
86 ipp[2] = at2.GetValue(2);
88 tmp = m_GdcmFile->GetEntryValue (0x0020, 0x0032);
89 rc = sscanf (tmp.c_str(), "%f\\%f\\%f", &ipp[0], &ipp[1], &ipp[2]);
91 itkExceptionMacro(<< "Error parsing RTDOSE ipp.");
96 #if GDCM_MAJOR_VERSION == 2
97 gdcm::Attribute<0x28,0x10> at3;
98 at3.SetFromDataSet(ds);
99 dim[1] = at3.GetValue();
101 tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0010);
102 rc = sscanf (tmp.c_str(), "%d", &dim[1]);
104 itkExceptionMacro(<< "Error parsing RTDOSE rows.");
109 #if GDCM_MAJOR_VERSION == 2
110 gdcm::Attribute<0x28,0x11> at4;
111 at4.SetFromDataSet(ds);
112 dim[0] = at4.GetValue();
114 tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0011);
115 rc = sscanf (tmp.c_str(), "%d", &dim[0]);
117 itkExceptionMacro(<< "Error parsing RTDOSE columns.");
122 #if GDCM_MAJOR_VERSION == 2
123 gdcm::Attribute<0x28,0x30> at5;
124 at5.SetFromDataSet(ds);
125 spacing[0] = at5.GetValue(0);
126 spacing[1] = at5.GetValue(1);
128 tmp = m_GdcmFile->GetEntryValue (0x0028, 0x0030);
129 rc = sscanf (tmp.c_str(), "%g\\%g", &spacing[0], &spacing[1]);
131 itkExceptionMacro(<< "Error parsing RTDOSE pixel spacing.");
135 /* GridFrameOffsetVector */
136 #if GDCM_MAJOR_VERSION == 2
137 gdcm::Attribute<0x3004,0x000C> at6;
138 const gdcm::DataElement& de6 = ds.GetDataElement( at6.GetTag() );
139 at6.SetFromDataElement(de6);
140 gfov = (double*) at6.GetValues();
141 gfov_len = at6.GetNumberOfValues();
143 tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000C);
146 gfov_str = tmp.c_str();
149 gfov = (double*) realloc (gfov, (gfov_len + 1) * sizeof(double));
150 rc = sscanf (gfov_str, "%g%n", &gfov[gfov_len], &len);
156 if (gfov_str[0] == '\\') {
164 itkExceptionMacro(<< "Error parsing RTDOSE gfov.");
167 /* --- Analyze GridFrameOffsetVector --- */
169 /* (1) Make sure first element is 0. */
171 itkExceptionMacro(<< "Error RTDOSE gfov[0] is not 0.");
174 /* (2) Handle case where gfov_len == 1 (only one slice). */
176 spacing[2] = spacing[0];
179 /* (3) Check to make sure spacing is regular. */
180 for (i = 1; i < gfov_len; i++) {
182 spacing[2] = gfov[1] - gfov[0];
184 double sp = gfov[i] - gfov[i-1];
185 if (fabs(sp - spacing[2]) > GFOV_SPACING_TOL) {
186 itkExceptionMacro(<< "Error RTDOSE grid has irregular spacing:"
187 << sp << " vs " << spacing[2]);
192 #if GDCM_MAJOR_VERSION < 2
196 /* DoseGridScaling */
197 #if GDCM_MAJOR_VERSION == 2
198 gdcm::Attribute<0x3004,0x000E> at7 = { 1. } ;
199 at7.SetFromDataSet(ds);
200 m_DoseScaling = at7.GetValue();
203 tmp = m_GdcmFile->GetEntryValue (0x3004, 0x000E);
204 rc = sscanf (tmp.c_str(), "%f", &m_DoseScaling);
206 /* If element doesn't exist, scaling is 1.0 */
208 // set dimension values
209 SetNumberOfDimensions(3);
210 for(int i=0; i<3; i++) {
211 SetDimensions(i, dim[i]);
212 SetSpacing(i, spacing[i]);
213 SetOrigin(i, ipp[i]);
216 // set other information
217 SetByteOrderToLittleEndian();
218 SetPixelType(itk::ImageIOBase::SCALAR);
219 SetNumberOfComponents(1);
220 SetComponentType(itk::ImageIOBase::FLOAT);
223 //--------------------------------------------------------------------
224 // Read Image Information
225 bool clitk::DicomRTDoseIO::CanReadFile(const char* FileNameToRead)
227 #if GDCM_MAJOR_VERSION == 2
228 gdcm::Reader creader;
229 creader.SetFileName(FileNameToRead);
233 gdcm::DataSet &ds = creader.GetFile().GetDataSet();
234 gdcm::Attribute<0x8,0x60> at1;
235 at1.SetFromDataSet(ds);
236 std::string tmp = at1.GetValue();
238 // opening dicom input file
240 dcmFile.SetFileName(FileNameToRead);
241 if (!dcmFile.OpenFile())
244 //Taken from plastimatch
245 dcmFile.SetMaxSizeLoadEntry (0xffff);
246 dcmFile.SetLoadMode (0);
249 /* Modality -- better be RTDOSE */
250 std::string tmp = dcmFile.GetEntryValue (0x0008, 0x0060);
252 if (!strncmp (tmp.c_str(), "RTDOSE", strlen("RTDOSE"))) {
259 //--------------------------------------------------------------------
262 clitk::DicomRTDoseIO::dose_copy_raw (float *img_out, T *img_in, int nvox, float scale)
264 for (int i = 0; i < nvox; i++) {
265 img_out[i] = img_in[i] * scale;
269 //--------------------------------------------------------------------
270 // Read Image Content
271 void clitk::DicomRTDoseIO::Read(void * buffer)
273 unsigned long npix = 1;
274 for(unsigned int i=0; i<GetNumberOfDimensions(); i++)
275 npix *= GetDimensions(i);
278 #if GDCM_MAJOR_VERSION == 2
279 gdcm::Image &i = m_GdcmImageReader.GetImage();
280 i.GetBuffer((char*)buffer);
282 float *img = (float*) buffer;
284 gdcm::FileHelper m_GdcmFile_helper (m_GdcmFile);
286 //size_t image_data_size = m_GdcmFile_helper.GetImageDataSize();
287 if (strcmp (m_GdcmFile->GetPixelType().c_str(), "16U")==0) {
288 unsigned short* image_data = (unsigned short*) m_GdcmFile_helper.GetImageData();
289 dose_copy_raw (img, image_data, npix, m_DoseScaling);
290 } else if (strcmp(m_GdcmFile->GetPixelType().c_str(),"32U")==0) {
291 unsigned long* image_data = (unsigned long*) m_GdcmFile_helper.GetImageData ();
292 dose_copy_raw (img, image_data, npix, m_DoseScaling);
294 itkExceptionMacro(<< "Error RTDOSE not type 16U and 32U (type="
295 << m_GdcmFile->GetPixelType().c_str() << ")");
300 /* GCS FIX: Do I need to do something about endian-ness? */
304 /* Copy data to volume */
305 // float *img = (float*) vol->img;
306 // for (i = 0; i < vol->npix; i++) {
307 //img[i] = image_data[i] * m_DoseScaling;
311 //--------------------------------------------------------------------
312 // Write Image Information
313 void clitk::DicomRTDoseIO::WriteImageInformation(bool keepOfStream)
317 //--------------------------------------------------------------------
318 // Write Image Information
319 bool clitk::DicomRTDoseIO::CanWriteFile(const char* FileNameToWrite)
324 //--------------------------------------------------------------------
326 void clitk::DicomRTDoseIO::Write(const void * buffer)