]> Creatis software - clitk.git/blob - common/clitkGateAsciiImageIO.cxx
Add rotate and translate option to clitkAffineTransform
[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 <cstdio>
21 #include <sstream>
22 #include <iostream>
23 using std::cout;
24 using std::endl;
25
26 // clitk include
27 #include "clitkGateAsciiImageIO.h"
28 #include "clitkCommon.h"
29
30 // itk include
31 #include <itkMetaDataObject.h>
32
33 std::ostream& operator<<(std::ostream& os, const clitk::GateAsciiImageIO::GateAsciiHeader& header)
34 {
35   os << "matrix_size=[" << header.matrix_size[0] << "," << header.matrix_size[1] << "," << header.matrix_size[2] << "]" << endl;
36   os << "resolution=[" << header.resolution[0] << "," << header.resolution[1] << "," << header.resolution[2] << "]" << endl;
37   os << "voxel_size=[" << header.voxel_size[0] << "," << header.voxel_size[1] << "," << header.voxel_size[2] << "]" << endl;
38   os << "nb_value=" << header.nb_value << endl;
39   return os;
40 }
41
42 //--------------------------------------------------------------------
43 // Read Image Information
44 void clitk::GateAsciiImageIO::ReadImageInformation()
45 {
46   FILE* handle = fopen(m_FileName.c_str(),"r");
47   if (!handle) {
48     itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
49     return;
50   }
51
52   GateAsciiHeader header;
53   if (!ReadHeader(handle,header)) {
54     itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
55     fclose(handle);
56     return;
57   }
58   fclose(handle);
59
60   int real_length = -1;
61   double real_spacing = 0;
62   for (int kk=0; kk<3; kk++) {
63     if (header.resolution[kk]>1) {
64       if (real_length>0) {
65         itkGenericExceptionMacro(<< "Could not image dimension: " << m_FileName);
66         return;
67       }
68       real_length = header.resolution[kk];
69       real_spacing = header.voxel_size[kk];
70     }
71   }
72   assert(real_length == header.nb_value);
73
74   // Set image information
75   SetNumberOfDimensions(2);
76   SetDimensions(0, real_length);
77   SetDimensions(1, 1);
78   SetSpacing(0, real_spacing);
79   SetSpacing(1, 1);
80   SetOrigin(0, 0);
81   SetOrigin(1, 0);
82   SetComponentType(itk::ImageIOBase::DOUBLE);
83 }
84
85 //--------------------------------------------------------------------
86 bool clitk::GateAsciiImageIO::CanReadFile(const char* FileNameToRead)
87 {
88   std::string filename(FileNameToRead);
89
90   {
91     // check extension
92     std::string filenameext = GetExtension(filename);
93     if (filenameext != "txt") return false;
94   }
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)) {
103       fclose(handle);
104       return false;
105     }
106     fclose(handle);
107   }
108
109   return true;
110 }
111
112 //--------------------------------------------------------------------
113 // Read Line in file
114 bool clitk::GateAsciiImageIO::ReadLine(FILE* handle, std::string& line)
115 {
116   std::stringstream stream;
117   while (true) {
118     char item;
119     if (ferror(handle)) return false;
120     if (fread(&item,1,1,handle) != 1) return false;
121
122     if (item=='\n' || feof(handle)) {
123       line = stream.str();
124       return true;
125     }
126
127     stream << item;
128   }
129 }
130
131 template <typename T>
132 T ConvertFromString(const std::string& value)
133 {
134   std::stringstream stream;
135   stream << value;
136   T converted;
137   stream >> converted;
138   return converted;
139 }
140
141 bool
142 clitk::GateAsciiImageIO::FindRegularExpressionNextLine(itksys::RegularExpression &reg, std::string &s, FILE* handle)
143 {
144   std::string line;
145   if(!ReadLine(handle,line))  return false;
146   if(!reg.compile(s.c_str())) return false;
147   return reg.find(line.c_str());
148 }
149
150 //--------------------------------------------------------------------
151 // Read Image Header
152 bool clitk::GateAsciiImageIO::ReadHeader(FILE* handle, GateAsciiHeader& header)
153 {
154   assert(handle);
155
156   std::string regexstr[6] = {
157     "^#.+$",
158     "^# +Matrix *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",
159     "^# +Resol *= +\\(([0-9]+),([0-9]+),([0-9]+)\\)$",
160     "^# +Voxel *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",
161     "^# +nbVal *= +([0-9]+)$"
162   };
163
164   itksys::RegularExpression regex;
165
166   if(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false;
167
168   if(!FindRegularExpressionNextLine(regex, regexstr[1], handle)) return false;
169   header.matrix_size[0] = ConvertFromString<double>(regex.match(1));
170   header.matrix_size[1] = ConvertFromString<double>(regex.match(2));
171   header.matrix_size[2] = ConvertFromString<double>(regex.match(3));
172
173   if(!FindRegularExpressionNextLine(regex, regexstr[2], handle)) return false;
174   header.resolution[0] = ConvertFromString<int>(regex.match(1));
175   header.resolution[1] = ConvertFromString<int>(regex.match(2));
176   header.resolution[2] = ConvertFromString<int>(regex.match(3));
177
178   if(!FindRegularExpressionNextLine(regex, regexstr[3], handle)) return false;
179   header.voxel_size[0] = ConvertFromString<double>(regex.match(1));
180   header.voxel_size[1] = ConvertFromString<double>(regex.match(2));
181   header.voxel_size[2] = ConvertFromString<double>(regex.match(3));
182
183   if(!FindRegularExpressionNextLine(regex, regexstr[4], handle)) return false;
184   header.nb_value = ConvertFromString<int>(regex.match(1));
185
186   if(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false;
187
188   return true;
189 }
190
191 //--------------------------------------------------------------------
192 // Read Image Content
193 void clitk::GateAsciiImageIO::Read(void* abstract_buffer)
194 {
195   FILE* handle = fopen(m_FileName.c_str(),"r");
196   if (!handle) {
197     itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
198     return;
199   }
200
201   GateAsciiHeader header;
202   if (!ReadHeader(handle,header)) {
203     itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
204     fclose(handle);
205     return;
206   }
207
208   {
209     double* buffer = static_cast<double*>(abstract_buffer);
210     int read_count = 0;
211     while (true) {
212       std::string line;
213       if (!ReadLine(handle,line)) break;
214       *buffer = ConvertFromString<double>(line);
215       read_count++;
216       buffer++;
217     }
218     assert(read_count == header.nb_value);
219   }
220
221   fclose(handle);
222 }
223
224 //--------------------------------------------------------------------
225 bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite)
226 {
227   if (GetExtension(std::string(FileNameToWrite)) != "txt") return false;
228   return true;
229 }
230
231 void clitk::GateAsciiImageIO::WriteImageInformation()
232 {
233   cout << GetNumberOfDimensions() << endl;
234 }
235
236 bool clitk::GateAsciiImageIO::SupportsDimension(unsigned long dim)
237 {
238   if (dim==2) return true;
239   return false;
240 }
241
242 //--------------------------------------------------------------------
243 // Write Image
244 void clitk::GateAsciiImageIO::Write(const void* abstract_buffer)
245 {
246   const unsigned long nb_value = GetDimensions(0)*GetDimensions(1);
247   std::stringstream stream;
248   stream << "######################" << endl;
249   stream << "# Matrix Size= (" << GetSpacing(0)*GetDimensions(0) << "," << GetSpacing(1)*GetDimensions(1) << ",1)" << endl;
250   stream << "# Resol      = (" << GetDimensions(0) << "," << GetDimensions(1) << ",1)" << endl;
251   stream << "# VoxelSize  = (" << GetSpacing(0) << "," << GetSpacing(1) << ",1)" << endl;
252   stream << "# nbVal      = " << nb_value << endl;
253   stream << "######################" << endl;
254
255   const double* buffer = static_cast<const double*>(abstract_buffer);
256   for (unsigned long kk=0; kk<nb_value; kk++) {
257     stream << buffer[kk] << endl;
258   }
259
260   FILE* handle = fopen(m_FileName.c_str(),"w");
261   if (!handle) {
262     itkGenericExceptionMacro(<< "Could not open file (for writing): " << m_FileName);
263     return;
264   }
265
266   fwrite(stream.str().c_str(),1,stream.str().size(),handle);
267
268   fclose(handle);
269 }