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://www.centreleonberard.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 ===========================================================================**/
28 #include "clitkGateAsciiImageIO.h"
29 #include "clitkCommon.h"
32 #include <itkMetaDataObject.h>
34 std::ostream& operator<<(std::ostream& os, const clitk::GateAsciiImageIO::GateAsciiHeader& header)
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;
43 //--------------------------------------------------------------------
44 // Read Image Information
45 void clitk::GateAsciiImageIO::ReadImageInformation()
47 FILE* handle = fopen(m_FileName.c_str(),"r");
49 itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
53 GateAsciiHeader header;
54 if (!ReadHeader(handle,header)) {
55 itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
62 double real_spacing = 0;
63 for (int kk=0; kk<3; kk++) {
64 if (header.resolution[kk]>1) {
66 itkGenericExceptionMacro(<< "Could not image dimension: " << m_FileName);
69 real_length = header.resolution[kk];
70 real_spacing = header.voxel_size[kk];
73 assert(real_length == header.nb_value);
75 // Set image information
76 SetNumberOfDimensions(2);
77 SetDimensions(0, real_length);
79 SetSpacing(0, real_spacing);
83 SetComponentType(itk::ImageIOBase::DOUBLE);
86 //--------------------------------------------------------------------
87 bool clitk::GateAsciiImageIO::CanReadFile(const char* FileNameToRead)
89 std::string filename(FileNameToRead);
92 std::string filenameext = GetExtension(filename);
93 if (filenameext != "txt") return false;
97 FILE* handle = fopen(filename.c_str(),"r");
98 if (!handle) return false;
100 GateAsciiHeader header;
101 if (!ReadHeader(handle,header)) { fclose(handle); return false; }
108 //--------------------------------------------------------------------
110 bool clitk::GateAsciiImageIO::ReadLine(FILE* handle, std::string& line)
112 std::stringstream stream;
116 if (ferror(handle)) return false;
117 if (fread(&item,1,1,handle) != 1) return false;
119 if (item=='\n' or feof(handle)) {
128 std::string ExtractMatch(const std::string& base, const regmatch_t& match)
130 return base.substr(match.rm_so,match.rm_eo-match.rm_so);
133 template <typename T>
134 T ConvertFromString(const std::string& value)
136 std::stringstream stream;
143 //--------------------------------------------------------------------
145 bool clitk::GateAsciiImageIO::ReadHeader(FILE* handle, GateAsciiHeader& header)
151 regex_t re_matrix_size;
153 regex_t re_voxel_size;
155 regmatch_t matches[4];
158 assert(regcomp(&re_comment,"^#.+$",REG_EXTENDED|REG_NEWLINE) == 0);
159 assert(regcomp(&re_matrix_size,"^# +Matrix *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE) == 0);
160 assert(regcomp(&re_resol,"^# +Resol *= +\\(([0-9]+),([0-9]+),([0-9]+)\\)$",REG_EXTENDED|REG_NEWLINE) == 0);
161 assert(regcomp(&re_voxel_size,"^# +Voxel *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE) == 0);
162 assert(regcomp(&re_nb_value,"^# +nbVal *= +([0-9]+)$",REG_EXTENDED|REG_NEWLINE) == 0);
165 if (!ReadLine(handle,line)) return false;
166 if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
168 if (!ReadLine(handle,line)) return false;
169 if (regexec(&re_matrix_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
170 header.matrix_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
171 header.matrix_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
172 header.matrix_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
174 if (!ReadLine(handle,line)) return false;
175 if (regexec(&re_resol,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
176 header.resolution[0] = ConvertFromString<int>(ExtractMatch(line,matches[1]));
177 header.resolution[1] = ConvertFromString<int>(ExtractMatch(line,matches[2]));
178 header.resolution[2] = ConvertFromString<int>(ExtractMatch(line,matches[3]));
180 if (!ReadLine(handle,line)) return false;
181 if (regexec(&re_voxel_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
182 header.voxel_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
183 header.voxel_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
184 header.voxel_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
186 if (!ReadLine(handle,line)) return false;
187 if (regexec(&re_nb_value,line.c_str(),2,matches,0) == REG_NOMATCH) return false;
188 header.nb_value = ConvertFromString<int>(ExtractMatch(line,matches[1]));
190 if (!ReadLine(handle,line)) return false;
191 if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
196 //--------------------------------------------------------------------
197 // Read Image Content
198 void clitk::GateAsciiImageIO::Read(void* abstract_buffer)
200 FILE* handle = fopen(m_FileName.c_str(),"r");
202 itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
206 GateAsciiHeader header;
207 if (!ReadHeader(handle,header)) {
208 itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
214 double* buffer = static_cast<double*>(abstract_buffer);
218 if (!ReadLine(handle,line)) break;
219 *buffer = ConvertFromString<double>(line);
223 assert(read_count == header.nb_value);
229 //--------------------------------------------------------------------
230 bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite)
232 if (GetExtension(std::string(FileNameToWrite)) != "txt") return false;
236 void clitk::GateAsciiImageIO::WriteImageInformation()
238 cout << GetNumberOfDimensions() << endl;
241 bool clitk::GateAsciiImageIO::SupportsDimension(unsigned long dim)
243 if (dim==2) return true;
247 //--------------------------------------------------------------------
249 void clitk::GateAsciiImageIO::Write(const void* abstract_buffer)
251 const unsigned long nb_value = GetDimensions(0)*GetDimensions(1);
252 std::stringstream stream;
253 stream << "######################" << endl;
254 stream << "# Matrix Size= (" << GetSpacing(0)*GetDimensions(0) << "," << GetSpacing(1)*GetDimensions(1) << ",1)" << endl;
255 stream << "# Resol = (" << GetDimensions(0) << "," << GetDimensions(1) << ",1)" << endl;
256 stream << "# VoxelSize = (" << GetSpacing(0) << "," << GetSpacing(1) << ",1)" << endl;
257 stream << "# nbVal = " << nb_value << endl;
258 stream << "######################" << endl;
260 const double* buffer = static_cast<const double*>(abstract_buffer);
261 for (unsigned long kk=0; kk<nb_value; kk++) { stream << buffer[kk] << endl; }
263 FILE* handle = fopen(m_FileName.c_str(),"w");
265 itkGenericExceptionMacro(<< "Could not open file (for writing): " << m_FileName);
269 fwrite(stream.str().c_str(),1,stream.str().size(),handle);