]> Creatis software - clitk.git/blob - common/rtkHndImageIO.cxx
Merge branch 'master' of git.creatis.insa-lyon.fr:clitk
[clitk.git] / common / rtkHndImageIO.cxx
1 /*=========================================================================
2  *
3  *  Copyright RTK Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18
19 // std include
20 #include <stdio.h>
21
22 #include "rtkHndImageIO.h"
23 #include <itkMetaDataObject.h>
24
25 //--------------------------------------------------------------------
26 // Read Image Information
27 void rtk::HndImageIO::ReadImageInformation()
28 {
29   Hnd_header hnd;
30   FILE *     fp;
31
32   fp = fopen (m_FileName.c_str(), "rb");
33   if (fp == NULL)
34     itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
35
36   size_t nelements = 0;
37   nelements += fread ( (void *) hnd.sFileType, sizeof(char), 32, fp);
38   nelements += fread ( (void *) &hnd.FileLength, sizeof(itk::uint32_t), 1, fp);
39   nelements += fread ( (void *) hnd.sChecksumSpec, sizeof(char), 4, fp);
40   nelements += fread ( (void *) &hnd.nCheckSum, sizeof(itk::uint32_t), 1, fp);
41   nelements += fread ( (void *) hnd.sCreationDate, sizeof(char), 8, fp);
42   nelements += fread ( (void *) hnd.sCreationTime, sizeof(char), 8, fp);
43   nelements += fread ( (void *) hnd.sPatientID, sizeof(char), 16, fp);
44   nelements += fread ( (void *) &hnd.nPatientSer, sizeof(itk::uint32_t), 1, fp);
45   nelements += fread ( (void *) hnd.sSeriesID, sizeof(char), 16, fp);
46   nelements += fread ( (void *) &hnd.nSeriesSer, sizeof(itk::uint32_t), 1, fp);
47   nelements += fread ( (void *) hnd.sSliceID, sizeof(char), 16, fp);
48   nelements += fread ( (void *) &hnd.nSliceSer, sizeof(itk::uint32_t), 1, fp);
49   nelements += fread ( (void *) &hnd.SizeX, sizeof(itk::uint32_t), 1, fp);
50   nelements += fread ( (void *) &hnd.SizeY, sizeof(itk::uint32_t), 1, fp);
51   nelements += fread ( (void *) &hnd.dSliceZPos, sizeof(double), 1, fp);
52   nelements += fread ( (void *) hnd.sModality, sizeof(char), 16, fp);
53   nelements += fread ( (void *) &hnd.nWindow, sizeof(itk::uint32_t), 1, fp);
54   nelements += fread ( (void *) &hnd.nLevel, sizeof(itk::uint32_t), 1, fp);
55   nelements += fread ( (void *) &hnd.nPixelOffset, sizeof(itk::uint32_t), 1, fp);
56   nelements += fread ( (void *) hnd.sImageType, sizeof(char), 4, fp);
57   nelements += fread ( (void *) &hnd.dGantryRtn, sizeof(double), 1, fp);
58   nelements += fread ( (void *) &hnd.dSAD, sizeof(double), 1, fp);
59   nelements += fread ( (void *) &hnd.dSFD, sizeof(double), 1, fp);
60   nelements += fread ( (void *) &hnd.dCollX1, sizeof(double), 1, fp);
61   nelements += fread ( (void *) &hnd.dCollX2, sizeof(double), 1, fp);
62   nelements += fread ( (void *) &hnd.dCollY1, sizeof(double), 1, fp);
63   nelements += fread ( (void *) &hnd.dCollY2, sizeof(double), 1, fp);
64   nelements += fread ( (void *) &hnd.dCollRtn, sizeof(double), 1, fp);
65   nelements += fread ( (void *) &hnd.dFieldX, sizeof(double), 1, fp);
66   nelements += fread ( (void *) &hnd.dFieldY, sizeof(double), 1, fp);
67   nelements += fread ( (void *) &hnd.dBladeX1, sizeof(double), 1, fp);
68   nelements += fread ( (void *) &hnd.dBladeX2, sizeof(double), 1, fp);
69   nelements += fread ( (void *) &hnd.dBladeY1, sizeof(double), 1, fp);
70   nelements += fread ( (void *) &hnd.dBladeY2, sizeof(double), 1, fp);
71   nelements += fread ( (void *) &hnd.dIDUPosLng, sizeof(double), 1, fp);
72   nelements += fread ( (void *) &hnd.dIDUPosLat, sizeof(double), 1, fp);
73   nelements += fread ( (void *) &hnd.dIDUPosVrt, sizeof(double), 1, fp);
74   nelements += fread ( (void *) &hnd.dIDUPosRtn, sizeof(double), 1, fp);
75   nelements += fread ( (void *) &hnd.dPatientSupportAngle, sizeof(double), 1, fp);
76   nelements += fread ( (void *) &hnd.dTableTopEccentricAngle, sizeof(double), 1, fp);
77   nelements += fread ( (void *) &hnd.dCouchVrt, sizeof(double), 1, fp);
78   nelements += fread ( (void *) &hnd.dCouchLng, sizeof(double), 1, fp);
79   nelements += fread ( (void *) &hnd.dCouchLat, sizeof(double), 1, fp);
80   nelements += fread ( (void *) &hnd.dIDUResolutionX, sizeof(double), 1, fp);
81   nelements += fread ( (void *) &hnd.dIDUResolutionY, sizeof(double), 1, fp);
82   nelements += fread ( (void *) &hnd.dImageResolutionX, sizeof(double), 1, fp);
83   nelements += fread ( (void *) &hnd.dImageResolutionY, sizeof(double), 1, fp);
84   nelements += fread ( (void *) &hnd.dEnergy, sizeof(double), 1, fp);
85   nelements += fread ( (void *) &hnd.dDoseRate, sizeof(double), 1, fp);
86   nelements += fread ( (void *) &hnd.dXRayKV, sizeof(double), 1, fp);
87   nelements += fread ( (void *) &hnd.dXRayMA, sizeof(double), 1, fp);
88   nelements += fread ( (void *) &hnd.dMetersetExposure, sizeof(double), 1, fp);
89   nelements += fread ( (void *) &hnd.dAcqAdjustment, sizeof(double), 1, fp);
90   nelements += fread ( (void *) &hnd.dCTProjectionAngle, sizeof(double), 1, fp);
91   nelements += fread ( (void *) &hnd.dCTNormChamber, sizeof(double), 1, fp);
92   nelements += fread ( (void *) &hnd.dGatingTimeTag, sizeof(double), 1, fp);
93   nelements += fread ( (void *) &hnd.dGating4DInfoX, sizeof(double), 1, fp);
94   nelements += fread ( (void *) &hnd.dGating4DInfoY, sizeof(double), 1, fp);
95   nelements += fread ( (void *) &hnd.dGating4DInfoZ, sizeof(double), 1, fp);
96   nelements += fread ( (void *) &hnd.dGating4DInfoTime, sizeof(double), 1, fp);
97
98   if(nelements != /*char*/120 + /*itk::uint32_t*/10 +  /*double*/41)
99     itkGenericExceptionMacro(<< "Could not read header data in " << m_FileName);
100
101   if(fclose (fp) != 0)
102     itkGenericExceptionMacro(<< "Could not close file: " << m_FileName);
103
104   /* Convert hnd to ITK image information */
105   SetNumberOfDimensions(2);
106   SetDimensions(0, hnd.SizeX);
107   SetDimensions(1, hnd.SizeY);
108   SetSpacing(0, hnd.dIDUResolutionX);
109   SetSpacing(1, hnd.dIDUResolutionY);
110   SetOrigin(0, -0.5*(hnd.SizeX-1)*hnd.dIDUResolutionX); //SR: assumed centered
111   SetOrigin(1, -0.5*(hnd.SizeY-1)*hnd.dIDUResolutionY); //SR: assumed centered
112   SetComponentType(itk::ImageIOBase::UINT);
113
114   /* Store important meta information in the meta data dictionary */
115   itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), "dCTProjectionAngle", hnd.dCTProjectionAngle);
116 }
117
118 //--------------------------------------------------------------------
119 bool rtk::HndImageIO::CanReadFile(const char* FileNameToRead)
120 {
121   std::string                  filename(FileNameToRead);
122   const std::string::size_type it = filename.find_last_of( "." );
123   std::string                  fileExt( filename, it+1, filename.length() );
124
125   if (fileExt != std::string("hnd") )
126     return false;
127   return true;
128 }
129
130 //--------------------------------------------------------------------
131 // Read Image Content
132 void rtk::HndImageIO::Read(void * buffer)
133 {
134   FILE *fp;
135
136   itk::uint32_t *buf = (itk::uint32_t*)buffer;
137   unsigned char *pt_lut;
138   itk::uint32_t  a;
139   unsigned char  v;
140   int            lut_idx, lut_off;
141   size_t         num_read;
142   char           dc;
143   short          ds;
144   long           dl, diff=0;
145   itk::uint32_t  i;
146
147   fp = fopen (m_FileName.c_str(), "rb");
148   if (fp == NULL)
149     itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
150
151   pt_lut = (unsigned char*) malloc (sizeof (unsigned char) * GetDimensions(0) * GetDimensions(1) );
152
153   /* Read LUT */
154   if(fseek (fp, 1024, SEEK_SET) != 0)
155     itkGenericExceptionMacro(<< "Could not seek to image data in: " << m_FileName);
156
157   size_t nbytes = (GetDimensions(1)-1)*GetDimensions(0) / 4;
158   if(nbytes != fread (pt_lut, sizeof(unsigned char), nbytes, fp))
159     itkGenericExceptionMacro(<< "Could not read image LUT in: " << m_FileName);
160
161   /* Read first row */
162   for (i = 0; i < GetDimensions(0); i++) {
163     if(1 != fread (&a, sizeof(itk::uint32_t), 1, fp))
164       itkGenericExceptionMacro(<< "Could not read first row in: " << m_FileName);
165     buf[i] = a;
166     }
167
168   /* Read first pixel of second row */
169   if(1 != fread (&a, sizeof(itk::uint32_t), 1, fp))
170     itkGenericExceptionMacro(<< "Could not read first pixel of second row");
171   buf[i++] = a;
172
173   /* Decompress the rest */
174   lut_idx = 0;
175   lut_off = 0;
176   while (i < GetDimensions(0) * GetDimensions(1) ) {
177     itk::uint32_t r11, r12, r21;
178
179     r11 = buf[i-GetDimensions(0)-1];
180     r12 = buf[i-GetDimensions(0)];
181     r21 = buf[i-1];
182     v = pt_lut[lut_idx];
183     switch (lut_off) {
184       case 0:
185         v = v & 0x03;
186         lut_off++;
187         break;
188       case 1:
189         v = (v & 0x0C) >> 2;
190         lut_off++;
191         break;
192       case 2:
193         v = (v & 0x30) >> 4;
194         lut_off++;
195         break;
196       case 3:
197         v = (v & 0xC0) >> 6;
198         lut_off = 0;
199         lut_idx++;
200         break;
201       }
202     switch (v) {
203       case 0:
204         num_read = fread (&dc, sizeof(unsigned char), 1, fp);
205         if (num_read != 1) goto read_error;
206         diff = dc;
207         break;
208       case 1:
209         num_read = fread (&ds, sizeof(unsigned short), 1, fp);
210         if (num_read != 1) goto read_error;
211         diff = ds;
212         break;
213       case 2:
214         num_read = fread (&dl, sizeof(itk::uint32_t), 1, fp);
215         if (num_read != 1) goto read_error;
216         diff = dl;
217         break;
218       }
219
220     buf[i] = r21 + r12 + diff - r11;
221     i++;
222     }
223
224   /* Clean up */
225   free (pt_lut);
226   if(fclose (fp) != 0)
227     itkGenericExceptionMacro(<< "Could not close file: " << m_FileName);
228   return;
229
230 read_error:
231
232   itkGenericExceptionMacro(<< "Error reading hnd file");
233   free (pt_lut);
234   if(fclose (fp) != 0)
235     itkGenericExceptionMacro(<< "Could not close file: " << m_FileName);
236   return;
237 }
238
239 //--------------------------------------------------------------------
240 bool rtk::HndImageIO::CanWriteFile(const char* itkNotUsed(FileNameToWrite))
241 {
242   return false;
243 }
244
245 //--------------------------------------------------------------------
246 // Write Image
247 void rtk::HndImageIO::Write(const void* itkNotUsed(buffer))
248 {
249   //TODO?
250 }