]> Creatis software - clitk.git/blob - common/clitkGateAsciiImageIO.cxx
read gate ascii file header
[clitk.git] / common / clitkGateAsciiImageIO.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
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.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18
19 // std include
20 #include <regex.h>
21 #include <cstdio>
22 #include <sstream>
23 #include <iostream>
24 using std::cout;
25 using std::endl;
26
27 // clitk include
28 #include "clitkGateAsciiImageIO.h"
29 #include "clitkCommon.h"
30
31 // itk include
32 #include <itkMetaDataObject.h>
33
34 std::ostream& operator<<(std::ostream& os, const clitk::GateAsciiImageIO::GateAsciiHeader& header)
35 {
36     os << "matrix_size=[" << header.matrix_size[0] << "," << header.matrix_size[1] << "," << header.matrix_size[2] << "]" << endl;
37     os << "resolution=[" << header.resolution[0] << "," << header.resolution[1] << "," << header.resolution[2] << "]" << endl;
38     os << "voxel_size=[" << header.voxel_size[0] << "," << header.voxel_size[1] << "," << header.voxel_size[2] << "]" << endl;
39     os << "nb_value=" << header.nb_value << endl;
40     return os;
41 }
42
43 //--------------------------------------------------------------------
44 // Read Image Information
45 void clitk::GateAsciiImageIO::ReadImageInformation()
46 {
47     itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
48
49
50     /* Convert hnd to ITK image information */
51     SetNumberOfDimensions(2);
52     //SetDimensions(0, hnd.SizeX);
53     //SetDimensions(1, hnd.SizeY);
54     //SetSpacing(0, hnd.dIDUResolutionX);
55     //SetSpacing(1, hnd.dIDUResolutionY);
56     //SetOrigin(0, -0.5*(hnd.SizeX-1)*hnd.dIDUResolutionX); //SR: assumed centered
57     //SetOrigin(1, -0.5*(hnd.SizeY-1)*hnd.dIDUResolutionY); //SR: assumed centered
58     //SetComponentType(itk::ImageIOBase::UINT);
59
60     /* Store important meta information in the meta data dictionary */
61     //itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), "dCTProjectionAngle", hnd.dCTProjectionAngle);
62     //itk::ExposeMetaData<double>( this->GetMetaDataDictionary(), &(hnd.dCTProjectionAngle), "dCTProjectionAngle");
63 }
64
65 //--------------------------------------------------------------------
66 bool clitk::GateAsciiImageIO::CanReadFile(const char* FileNameToRead)
67 {
68     std::string filename(FileNameToRead);
69
70     { // check extension
71         std::string filenameext = GetExtension(filename);
72         if (filenameext != std::string("txt")) return false;
73     }
74
75     { // check header
76         FILE* handle = fopen(filename.c_str(),"r");
77         if (!handle) return false;
78
79         GateAsciiHeader header;
80         if (!ReadHeader(handle,header)) { fclose(handle); return false; }
81         fclose(handle);
82     }
83
84     return true;
85 }
86
87 //--------------------------------------------------------------------
88 // Read Line in file
89 bool clitk::GateAsciiImageIO::ReadLine(FILE* handle, std::string& line)
90 {
91     std::stringstream stream;
92     while (true)
93     {
94         char item;
95         if (ferror(handle)) return false;
96         if (fread(&item,1,1,handle) != 1) return false;
97
98         if (item=='\n' or feof(handle)) {
99             line = stream.str();
100             return true;
101         }
102
103         stream << item;
104     }
105 }
106
107 std::string ExtractMatch(const std::string& base, const regmatch_t& match) 
108 {
109     return base.substr(match.rm_so,match.rm_eo-match.rm_so);
110 }
111
112 template <typename T>
113 T ConvertFromString(const std::string& value)
114 {
115     std::stringstream stream;
116     stream << value;
117     T converted;
118     stream >> converted;
119     return converted;
120 }
121
122 //--------------------------------------------------------------------
123 // Read Image Header
124 bool clitk::GateAsciiImageIO::ReadHeader(FILE* handle, GateAsciiHeader& header)
125 {
126     assert(handle);
127     std::string line;
128
129     regex_t re_comment;
130     regex_t re_matrix_size;
131     regex_t re_resol;
132     regex_t re_voxel_size;
133     regex_t re_nb_value;
134     regmatch_t matches[4];
135
136     { // build regex
137         int ret = 0;
138         ret = regcomp(&re_comment,"^#.+$",REG_EXTENDED|REG_NEWLINE);
139         assert(ret);
140         ret = regcomp(&re_matrix_size,"^# +Matrix *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
141         assert(ret);
142         ret = regcomp(&re_resol,"^# +Resol *= +\\(([0-9]+),([0-9]+),([0-9]+)\\)$",REG_EXTENDED|REG_NEWLINE);
143         assert(ret);
144         ret = regcomp(&re_voxel_size,"^# +Voxel *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
145         assert(ret);
146         ret = regcomp(&re_nb_value,"^# +nbVal *= +([0-9]+)$",REG_EXTENDED|REG_NEWLINE);
147         assert(ret);
148     }
149
150     if (!ReadLine(handle,line)) return false;
151     if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
152
153     if (!ReadLine(handle,line)) return false;
154     if (regexec(&re_matrix_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
155     header.matrix_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
156     header.matrix_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
157     header.matrix_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
158
159     if (!ReadLine(handle,line)) return false;
160     if (regexec(&re_resol,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
161     header.resolution[0] = ConvertFromString<int>(ExtractMatch(line,matches[1]));
162     header.resolution[1] = ConvertFromString<int>(ExtractMatch(line,matches[2]));
163     header.resolution[2] = ConvertFromString<int>(ExtractMatch(line,matches[3]));
164
165     if (!ReadLine(handle,line)) return false;
166     if (regexec(&re_voxel_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
167     header.voxel_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
168     header.voxel_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
169     header.voxel_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
170
171     if (!ReadLine(handle,line)) return false;
172     if (regexec(&re_nb_value,line.c_str(),2,matches,0) == REG_NOMATCH) return false;
173     header.nb_value = ConvertFromString<int>(ExtractMatch(line,matches[1]));
174
175     if (!ReadLine(handle,line)) return false;
176     if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
177
178     return true;
179 }
180
181 //--------------------------------------------------------------------
182 // Read Image Content
183 void clitk::GateAsciiImageIO::Read(void * buffer)
184 {
185   FILE *fp;
186
187   uint32_t* buf = (uint32_t*)buffer;
188   unsigned char *pt_lut;
189   uint32_t a;
190   float b;
191   unsigned char v;
192   int lut_idx, lut_off;
193   size_t num_read;
194   char dc;
195   short ds;
196   long dl, diff=0;
197   uint32_t i;
198
199   fp = fopen (m_FileName.c_str(), "rb");
200   if (fp == NULL)
201     itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
202
203   pt_lut = (unsigned char*) malloc (sizeof (unsigned char) * GetDimensions(0) * GetDimensions(1));
204
205   /* Read LUT */
206   fseek (fp, 1024, SEEK_SET);
207   fread (pt_lut, sizeof(unsigned char), (GetDimensions(1)-1)*GetDimensions(0) / 4, fp);
208
209   /* Read first row */
210   for (i = 0; i < GetDimensions(0); i++) {
211     fread (&a, sizeof(uint32_t), 1, fp);
212     buf[i] = a;
213     b = a;
214   }
215
216   /* Read first pixel of second row */
217   fread (&a, sizeof(uint32_t), 1, fp);
218   buf[i++] = a;
219   b = a;
220
221   /* Decompress the rest */
222   lut_idx = 0;
223   lut_off = 0;
224   while (i < GetDimensions(0) * GetDimensions(1)) {
225     uint32_t r11, r12, r21;
226
227     r11 = buf[i-GetDimensions(0)-1];
228     r12 = buf[i-GetDimensions(0)];
229     r21 = buf[i-1];
230     v = pt_lut[lut_idx];
231     switch (lut_off) {
232     case 0:
233       v = v & 0x03;
234       lut_off ++;
235       break;
236     case 1:
237       v = (v & 0x0C) >> 2;
238       lut_off ++;
239       break;
240     case 2:
241       v = (v & 0x30) >> 4;
242       lut_off ++;
243       break;
244     case 3:
245       v = (v & 0xC0) >> 6;
246       lut_off = 0;
247       lut_idx ++;
248       break;
249     }
250     switch (v) {
251     case 0:
252       num_read = fread (&dc, sizeof(unsigned char), 1, fp);
253       if (num_read != 1) goto read_error;
254       diff = dc;
255       break;
256     case 1:
257       num_read = fread (&ds, sizeof(unsigned short), 1, fp);
258       if (num_read != 1) goto read_error;
259       diff = ds;
260       break;
261     case 2:
262       num_read = fread (&dl, sizeof(uint32_t), 1, fp);
263       if (num_read != 1) goto read_error;
264       diff = dl;
265       break;
266     }
267
268     buf[i] = r21 + r12 + diff - r11;
269     b = buf[i];
270     i++;
271   }
272
273   /* Clean up */
274   free (pt_lut);
275   fclose (fp);
276   return;
277
278 read_error:
279
280   itkGenericExceptionMacro(<< "Error reading gate ascii file");
281   free (pt_lut);
282   fclose (fp);
283   return;
284 }
285
286 //--------------------------------------------------------------------
287 bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite)
288 {
289   return false;
290 }
291
292 //--------------------------------------------------------------------
293 // Write Image
294 void clitk::GateAsciiImageIO::Write(const void* buffer)
295 {
296 }