]> Creatis software - clitk.git/blob - common/clitkGateAsciiImageIO.cxx
reading for gate ascii format
[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     FILE* handle = fopen(m_FileName.c_str(),"r");
48     if (!handle) {
49         itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
50         return;
51     }
52
53     GateAsciiHeader header;
54     if (!ReadHeader(handle,header)) {
55         itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
56         fclose(handle);
57         return;
58     }
59     fclose(handle);
60
61     int real_length = -1;
62     double real_spacing = 0;
63     for (int kk=0; kk<3; kk++) {
64         if (header.resolution[kk]>1) {
65             if (real_length>0) {
66                 itkGenericExceptionMacro(<< "Could not image dimension: " << m_FileName);
67                 return;
68             }
69             real_length = header.resolution[kk];
70             real_spacing = header.voxel_size[kk];
71         }
72     }
73     assert(real_length == header.nb_value);
74
75
76     // Set image information
77     SetNumberOfDimensions(2);
78     SetDimensions(0, real_length);
79     SetDimensions(1, 1);
80     SetSpacing(0, real_spacing);
81     SetSpacing(1, 1);
82     SetOrigin(0, 0);
83     SetOrigin(1, 0);
84     SetComponentType(itk::ImageIOBase::DOUBLE);
85 }
86
87 //--------------------------------------------------------------------
88 bool clitk::GateAsciiImageIO::CanReadFile(const char* FileNameToRead)
89 {
90     std::string filename(FileNameToRead);
91
92     { // check extension
93         std::string filenameext = GetExtension(filename);
94         if (filenameext != std::string("txt")) return false;
95     }
96
97     { // check header
98         FILE* handle = fopen(filename.c_str(),"r");
99         if (!handle) return false;
100
101         GateAsciiHeader header;
102         if (!ReadHeader(handle,header)) { fclose(handle); return false; }
103         fclose(handle);
104     }
105
106     return true;
107 }
108
109 //--------------------------------------------------------------------
110 // Read Line in file
111 bool clitk::GateAsciiImageIO::ReadLine(FILE* handle, std::string& line)
112 {
113     std::stringstream stream;
114     while (true)
115     {
116         char item;
117         if (ferror(handle)) return false;
118         if (fread(&item,1,1,handle) != 1) return false;
119
120         if (item=='\n' or feof(handle)) {
121             line = stream.str();
122             return true;
123         }
124
125         stream << item;
126     }
127 }
128
129 std::string ExtractMatch(const std::string& base, const regmatch_t& match) 
130 {
131     return base.substr(match.rm_so,match.rm_eo-match.rm_so);
132 }
133
134 template <typename T>
135 T ConvertFromString(const std::string& value)
136 {
137     std::stringstream stream;
138     stream << value;
139     T converted;
140     stream >> converted;
141     return converted;
142 }
143
144 //--------------------------------------------------------------------
145 // Read Image Header
146 bool clitk::GateAsciiImageIO::ReadHeader(FILE* handle, GateAsciiHeader& header)
147 {
148     assert(handle);
149     std::string line;
150
151     regex_t re_comment;
152     regex_t re_matrix_size;
153     regex_t re_resol;
154     regex_t re_voxel_size;
155     regex_t re_nb_value;
156     regmatch_t matches[4];
157
158     { // build regex
159         int ret = 0;
160         ret = regcomp(&re_comment,"^#.+$",REG_EXTENDED|REG_NEWLINE);
161         assert(ret == 0);
162         ret = regcomp(&re_matrix_size,"^# +Matrix *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
163         assert(ret == 0);
164         ret = regcomp(&re_resol,"^# +Resol *= +\\(([0-9]+),([0-9]+),([0-9]+)\\)$",REG_EXTENDED|REG_NEWLINE);
165         assert(ret == 0);
166         ret = regcomp(&re_voxel_size,"^# +Voxel *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
167         assert(ret == 0);
168         ret = regcomp(&re_nb_value,"^# +nbVal *= +([0-9]+)$",REG_EXTENDED|REG_NEWLINE);
169         assert(ret == 0);
170     }
171
172     if (!ReadLine(handle,line)) return false;
173     if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
174
175     if (!ReadLine(handle,line)) return false;
176     if (regexec(&re_matrix_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
177     header.matrix_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
178     header.matrix_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
179     header.matrix_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
180
181     if (!ReadLine(handle,line)) return false;
182     if (regexec(&re_resol,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
183     header.resolution[0] = ConvertFromString<int>(ExtractMatch(line,matches[1]));
184     header.resolution[1] = ConvertFromString<int>(ExtractMatch(line,matches[2]));
185     header.resolution[2] = ConvertFromString<int>(ExtractMatch(line,matches[3]));
186
187     if (!ReadLine(handle,line)) return false;
188     if (regexec(&re_voxel_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
189     header.voxel_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
190     header.voxel_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
191     header.voxel_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
192
193     if (!ReadLine(handle,line)) return false;
194     if (regexec(&re_nb_value,line.c_str(),2,matches,0) == REG_NOMATCH) return false;
195     header.nb_value = ConvertFromString<int>(ExtractMatch(line,matches[1]));
196
197     if (!ReadLine(handle,line)) return false;
198     if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
199
200     return true;
201 }
202
203 //--------------------------------------------------------------------
204 // Read Image Content
205 void clitk::GateAsciiImageIO::Read(void* abstract_buffer)
206 {
207     FILE* handle = fopen(m_FileName.c_str(),"r");
208     if (!handle) {
209         itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
210         return;
211     }
212
213     GateAsciiHeader header;
214     if (!ReadHeader(handle,header)) {
215         itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
216         fclose(handle);
217         return;
218     }
219
220     {
221         double* buffer = static_cast<double*>(abstract_buffer);
222         int read_count = 0;
223         while (true) { 
224             std::string line;
225             if (!ReadLine(handle,line)) break;
226             *buffer = ConvertFromString<double>(line);
227             read_count++;
228             buffer++;
229         }
230         assert(read_count == header.nb_value);
231     }
232
233     fclose(handle);
234 }
235
236 //--------------------------------------------------------------------
237 bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite)
238 {
239   return false;
240 }
241
242 //--------------------------------------------------------------------
243 // Write Image
244 void clitk::GateAsciiImageIO::Write(const void* buffer)
245 {
246 }