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 ===========================================================================**/
27 #include "clitkGateAsciiImageIO.h"
28 #include "clitkCommon.h"
31 #include <itkMetaDataObject.h>
33 std::ostream& operator<<(std::ostream& os, const clitk::GateAsciiImageIO::GateAsciiHeader& header)
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;
42 //--------------------------------------------------------------------
43 // Read Image Information
44 void clitk::GateAsciiImageIO::ReadImageInformation()
46 FILE* handle = fopen(m_FileName.c_str(),"r");
48 itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
52 GateAsciiHeader header;
53 if (!ReadHeader(handle,header)) {
54 itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
61 double real_spacing = 0;
62 for (int kk=0; kk<3; kk++) {
63 if (header.resolution[kk]>1) {
65 itkGenericExceptionMacro(<< "Could not image dimension: " << m_FileName);
68 real_length = header.resolution[kk];
69 real_spacing = header.voxel_size[kk];
72 assert(real_length == header.nb_value);
74 // Set image information
75 SetNumberOfDimensions(2);
76 SetDimensions(0, real_length);
78 SetSpacing(0, real_spacing);
82 SetComponentType(itk::ImageIOBase::DOUBLE);
85 //--------------------------------------------------------------------
86 bool clitk::GateAsciiImageIO::CanReadFile(const char* FileNameToRead)
88 std::string filename(FileNameToRead);
92 std::string filenameext = GetExtension(filename);
93 if (filenameext != "txt") return false;
98 FILE* handle = fopen(filename.c_str(),"r");
99 if (!handle) return false;
101 GateAsciiHeader header;
102 if (!ReadHeader(handle,header)) {
112 //--------------------------------------------------------------------
114 bool clitk::GateAsciiImageIO::ReadLine(FILE* handle, std::string& line)
116 std::stringstream stream;
119 if (ferror(handle)) return false;
120 if (fread(&item,1,1,handle) != 1) return false;
122 if (item=='\n' || feof(handle)) {
131 template <typename T>
132 T ConvertFromString(const std::string& value)
134 std::stringstream stream;
142 clitk::GateAsciiImageIO::FindRegularExpressionNextLine(itksys::RegularExpression ®, std::string &s, FILE* handle)
145 if(!ReadLine(handle,line)) return false;
146 if(!reg.compile(s.c_str())) return false;
147 return reg.find(line.c_str());
150 //--------------------------------------------------------------------
152 bool clitk::GateAsciiImageIO::ReadHeader(FILE* handle, GateAsciiHeader& header)
156 std::string regexstr[6] = {
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]+)$"
164 itksys::RegularExpression regex;
166 if(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false;
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));
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));
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));
183 if(!FindRegularExpressionNextLine(regex, regexstr[4], handle)) return false;
184 header.nb_value = ConvertFromString<int>(regex.match(1));
186 if(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false;
191 //--------------------------------------------------------------------
192 // Read Image Content
193 void clitk::GateAsciiImageIO::Read(void* abstract_buffer)
195 FILE* handle = fopen(m_FileName.c_str(),"r");
197 itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
201 GateAsciiHeader header;
202 if (!ReadHeader(handle,header)) {
203 itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
209 double* buffer = static_cast<double*>(abstract_buffer);
213 if (!ReadLine(handle,line)) break;
214 *buffer = ConvertFromString<double>(line);
218 assert(read_count == header.nb_value);
224 //--------------------------------------------------------------------
225 bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite)
227 if (GetExtension(std::string(FileNameToWrite)) != "txt") return false;
231 void clitk::GateAsciiImageIO::WriteImageInformation()
233 cout << GetNumberOfDimensions() << endl;
236 bool clitk::GateAsciiImageIO::SupportsDimension(unsigned long dim)
238 if (dim==2) return true;
242 //--------------------------------------------------------------------
244 void clitk::GateAsciiImageIO::Write(const void* abstract_buffer)
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;
255 if(this->GetComponentType()==itk::ImageIOBase::UCHAR) {
256 const unsigned char* buffer = static_cast<const unsigned char*>(abstract_buffer);
257 for (unsigned long kk=0; kk<nb_value; kk++)
258 stream << buffer[kk] << endl;
259 } else if(this->GetComponentType()==itk::ImageIOBase::CHAR) {
260 const char* buffer = static_cast<const char*>(abstract_buffer);
261 for (unsigned long kk=0; kk<nb_value; kk++)
262 stream << buffer[kk] << endl;
263 } else if(this->GetComponentType()==itk::ImageIOBase::USHORT) {
264 const unsigned short* buffer = static_cast<const unsigned short*>(abstract_buffer);
265 for (unsigned long kk=0; kk<nb_value; kk++)
266 stream << buffer[kk] << endl;
267 } else if(this->GetComponentType()==itk::ImageIOBase::SHORT) {
268 const short* buffer = static_cast<const short*>(abstract_buffer);
269 for (unsigned long kk=0; kk<nb_value; kk++)
270 stream << buffer[kk] << endl;
271 } else if(this->GetComponentType()==itk::ImageIOBase::UINT) {
272 const unsigned int* buffer = static_cast<const unsigned int*>(abstract_buffer);
273 for (unsigned long kk=0; kk<nb_value; kk++)
274 stream << buffer[kk] << endl;
275 } else if(this->GetComponentType()==itk::ImageIOBase::INT) {
276 const int* buffer = static_cast<const int*>(abstract_buffer);
277 for (unsigned long kk=0; kk<nb_value; kk++)
278 stream << buffer[kk] << endl;
279 } else if(this->GetComponentType()==itk::ImageIOBase::ULONG) {
280 const unsigned long* buffer = static_cast<const unsigned long*>(abstract_buffer);
281 for (unsigned long kk=0; kk<nb_value; kk++)
282 stream << buffer[kk] << endl;
283 } else if(this->GetComponentType()==itk::ImageIOBase::LONG) {
284 const long* buffer = static_cast<const long*>(abstract_buffer);
285 for (unsigned long kk=0; kk<nb_value; kk++)
286 stream << buffer[kk] << endl;
287 } else if(this->GetComponentType()==itk::ImageIOBase::FLOAT) {
288 const float* buffer = static_cast<const float*>(abstract_buffer);
289 for (unsigned long kk=0; kk<nb_value; kk++)
290 stream << buffer[kk] << endl;
291 } else if(this->GetComponentType()==itk::ImageIOBase::DOUBLE) {
292 const double* buffer = static_cast<const double*>(abstract_buffer);
293 for (unsigned long kk=0; kk<nb_value; kk++)
294 stream << buffer[kk] << endl;
296 itkGenericExceptionMacro(<< "Unhandled pixel type: " << this->GetComponentTypeAsString(this->GetComponentType()));
300 FILE* handle = fopen(m_FileName.c_str(),"w");
302 itkGenericExceptionMacro(<< "Could not open file (for writing): " << m_FileName);
306 fwrite(stream.str().c_str(),1,stream.str().size(),handle);