===========================================================================**/
// std include
-#include <regex.h>
#include <cstdio>
#include <sstream>
#include <iostream>
std::ostream& operator<<(std::ostream& os, const clitk::GateAsciiImageIO::GateAsciiHeader& header)
{
- os << "matrix_size=[" << header.matrix_size[0] << "," << header.matrix_size[1] << "," << header.matrix_size[2] << "]" << endl;
- os << "resolution=[" << header.resolution[0] << "," << header.resolution[1] << "," << header.resolution[2] << "]" << endl;
- os << "voxel_size=[" << header.voxel_size[0] << "," << header.voxel_size[1] << "," << header.voxel_size[2] << "]" << endl;
- os << "nb_value=" << header.nb_value << endl;
- return os;
+ os << "matrix_size=[" << header.matrix_size[0] << "," << header.matrix_size[1] << "," << header.matrix_size[2] << "]" << endl;
+ os << "resolution=[" << header.resolution[0] << "," << header.resolution[1] << "," << header.resolution[2] << "]" << endl;
+ os << "voxel_size=[" << header.voxel_size[0] << "," << header.voxel_size[1] << "," << header.voxel_size[2] << "]" << endl;
+ os << "nb_value=" << header.nb_value << endl;
+ return os;
}
//--------------------------------------------------------------------
// Read Image Information
void clitk::GateAsciiImageIO::ReadImageInformation()
{
+ FILE* handle = fopen(m_FileName.c_str(),"r");
+ if (!handle) {
itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
+ return;
+ }
-
- /* Convert hnd to ITK image information */
- SetNumberOfDimensions(2);
- //SetDimensions(0, hnd.SizeX);
- //SetDimensions(1, hnd.SizeY);
- //SetSpacing(0, hnd.dIDUResolutionX);
- //SetSpacing(1, hnd.dIDUResolutionY);
- //SetOrigin(0, -0.5*(hnd.SizeX-1)*hnd.dIDUResolutionX); //SR: assumed centered
- //SetOrigin(1, -0.5*(hnd.SizeY-1)*hnd.dIDUResolutionY); //SR: assumed centered
- //SetComponentType(itk::ImageIOBase::UINT);
-
- /* Store important meta information in the meta data dictionary */
- //itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), "dCTProjectionAngle", hnd.dCTProjectionAngle);
- //itk::ExposeMetaData<double>( this->GetMetaDataDictionary(), &(hnd.dCTProjectionAngle), "dCTProjectionAngle");
+ GateAsciiHeader header;
+ if (!ReadHeader(handle,header)) {
+ itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
+ fclose(handle);
+ return;
+ }
+ fclose(handle);
+
+ int real_length = -1;
+ double real_spacing = 0;
+ for (int kk=0; kk<3; kk++) {
+ if (header.resolution[kk]>1) {
+ if (real_length>0) {
+ itkGenericExceptionMacro(<< "Could not image dimension: " << m_FileName);
+ return;
+ }
+ real_length = header.resolution[kk];
+ real_spacing = header.voxel_size[kk];
+ }
+ }
+ assert(real_length == header.nb_value);
+
+ // Set image information
+ SetNumberOfDimensions(2);
+ SetDimensions(0, real_length);
+ SetDimensions(1, 1);
+ SetSpacing(0, real_spacing);
+ SetSpacing(1, 1);
+ SetOrigin(0, 0);
+ SetOrigin(1, 0);
+ SetComponentType(itk::ImageIOBase::DOUBLE);
}
//--------------------------------------------------------------------
bool clitk::GateAsciiImageIO::CanReadFile(const char* FileNameToRead)
{
- std::string filename(FileNameToRead);
+ std::string filename(FileNameToRead);
- { // check extension
- std::string filenameext = GetExtension(filename);
- if (filenameext != std::string("txt")) return false;
- }
+ {
+ // check extension
+ std::string filenameext = GetExtension(filename);
+ if (filenameext != "txt") return false;
+ }
- { // check header
- FILE* handle = fopen(filename.c_str(),"r");
- if (!handle) return false;
+ {
+ // check header
+ FILE* handle = fopen(filename.c_str(),"r");
+ if (!handle) return false;
- GateAsciiHeader header;
- if (!ReadHeader(handle,header)) { fclose(handle); return false; }
- fclose(handle);
+ GateAsciiHeader header;
+ if (!ReadHeader(handle,header)) {
+ fclose(handle);
+ return false;
}
+ fclose(handle);
+ }
- return true;
+ return true;
}
//--------------------------------------------------------------------
// Read Line in file
bool clitk::GateAsciiImageIO::ReadLine(FILE* handle, std::string& line)
{
- std::stringstream stream;
- while (true)
- {
- char item;
- if (ferror(handle)) return false;
- if (fread(&item,1,1,handle) != 1) return false;
-
- if (item=='\n' or feof(handle)) {
- line = stream.str();
- return true;
- }
-
- stream << item;
+ std::stringstream stream;
+ while (true) {
+ char item;
+ if (ferror(handle)) return false;
+ if (fread(&item,1,1,handle) != 1) return false;
+
+ if (item=='\n' || feof(handle)) {
+ line = stream.str();
+ return true;
}
-}
-std::string ExtractMatch(const std::string& base, const regmatch_t& match)
-{
- return base.substr(match.rm_so,match.rm_eo-match.rm_so);
+ stream << item;
+ }
}
template <typename T>
T ConvertFromString(const std::string& value)
{
- std::stringstream stream;
- stream << value;
- T converted;
- stream >> converted;
- return converted;
+ std::stringstream stream;
+ stream << value;
+ T converted;
+ stream >> converted;
+ return converted;
+}
+
+bool
+clitk::GateAsciiImageIO::FindRegularExpressionNextLine(itksys::RegularExpression ®, std::string &s, FILE* handle)
+{
+ std::string line;
+ if(!ReadLine(handle,line)) return false;
+ if(!reg.compile(s.c_str())) return false;
+ return reg.find(line.c_str());
}
//--------------------------------------------------------------------
// Read Image Header
bool clitk::GateAsciiImageIO::ReadHeader(FILE* handle, GateAsciiHeader& header)
{
- assert(handle);
- std::string line;
-
- regex_t re_comment;
- regex_t re_matrix_size;
- regex_t re_resol;
- regex_t re_voxel_size;
- regex_t re_nb_value;
- regmatch_t matches[4];
-
- { // build regex
- int ret = 0;
- ret = regcomp(&re_comment,"^#.+$",REG_EXTENDED|REG_NEWLINE);
- assert(ret);
- ret = regcomp(&re_matrix_size,"^# +Matrix *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
- assert(ret);
- ret = regcomp(&re_resol,"^# +Resol *= +\\(([0-9]+),([0-9]+),([0-9]+)\\)$",REG_EXTENDED|REG_NEWLINE);
- assert(ret);
- ret = regcomp(&re_voxel_size,"^# +Voxel *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",REG_EXTENDED|REG_NEWLINE);
- assert(ret);
- ret = regcomp(&re_nb_value,"^# +nbVal *= +([0-9]+)$",REG_EXTENDED|REG_NEWLINE);
- assert(ret);
- }
+ assert(handle);
+
+ std::string regexstr[6] = {
+ "^#.+$",
+ "^# +Matrix *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",
+ "^# +Resol *= +\\(([0-9]+),([0-9]+),([0-9]+)\\)$",
+ "^# +Voxel *Size *= +\\(([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*),([0-9]+\\.?[0-9]*)\\)$",
+ "^# +nbVal *= +([0-9]+)$"
+ };
+
+ itksys::RegularExpression regex;
- if (!ReadLine(handle,line)) return false;
- if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
+ if(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false;
- if (!ReadLine(handle,line)) return false;
- if (regexec(&re_matrix_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
- header.matrix_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
- header.matrix_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
- header.matrix_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
+ if(!FindRegularExpressionNextLine(regex, regexstr[1], handle)) return false;
+ header.matrix_size[0] = ConvertFromString<double>(regex.match(1));
+ header.matrix_size[1] = ConvertFromString<double>(regex.match(2));
+ header.matrix_size[2] = ConvertFromString<double>(regex.match(3));
- if (!ReadLine(handle,line)) return false;
- if (regexec(&re_resol,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
- header.resolution[0] = ConvertFromString<int>(ExtractMatch(line,matches[1]));
- header.resolution[1] = ConvertFromString<int>(ExtractMatch(line,matches[2]));
- header.resolution[2] = ConvertFromString<int>(ExtractMatch(line,matches[3]));
+ if(!FindRegularExpressionNextLine(regex, regexstr[2], handle)) return false;
+ header.resolution[0] = ConvertFromString<int>(regex.match(1));
+ header.resolution[1] = ConvertFromString<int>(regex.match(2));
+ header.resolution[2] = ConvertFromString<int>(regex.match(3));
- if (!ReadLine(handle,line)) return false;
- if (regexec(&re_voxel_size,line.c_str(),4,matches,0) == REG_NOMATCH) return false;
- header.voxel_size[0] = ConvertFromString<double>(ExtractMatch(line,matches[1]));
- header.voxel_size[1] = ConvertFromString<double>(ExtractMatch(line,matches[2]));
- header.voxel_size[2] = ConvertFromString<double>(ExtractMatch(line,matches[3]));
+ if(!FindRegularExpressionNextLine(regex, regexstr[3], handle)) return false;
+ header.voxel_size[0] = ConvertFromString<double>(regex.match(1));
+ header.voxel_size[1] = ConvertFromString<double>(regex.match(2));
+ header.voxel_size[2] = ConvertFromString<double>(regex.match(3));
- if (!ReadLine(handle,line)) return false;
- if (regexec(&re_nb_value,line.c_str(),2,matches,0) == REG_NOMATCH) return false;
- header.nb_value = ConvertFromString<int>(ExtractMatch(line,matches[1]));
+ if(!FindRegularExpressionNextLine(regex, regexstr[4], handle)) return false;
+ header.nb_value = ConvertFromString<int>(regex.match(1));
- if (!ReadLine(handle,line)) return false;
- if (regexec(&re_comment,line.c_str(),1,matches,0) == REG_NOMATCH) return false;
+ if(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false;
- return true;
+ return true;
}
//--------------------------------------------------------------------
// Read Image Content
-void clitk::GateAsciiImageIO::Read(void * buffer)
+void clitk::GateAsciiImageIO::Read(void* abstract_buffer)
{
- FILE *fp;
-
- uint32_t* buf = (uint32_t*)buffer;
- unsigned char *pt_lut;
- uint32_t a;
- float b;
- unsigned char v;
- int lut_idx, lut_off;
- size_t num_read;
- char dc;
- short ds;
- long dl, diff=0;
- uint32_t i;
-
- fp = fopen (m_FileName.c_str(), "rb");
- if (fp == NULL)
+ FILE* handle = fopen(m_FileName.c_str(),"r");
+ if (!handle) {
itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName);
+ return;
+ }
- pt_lut = (unsigned char*) malloc (sizeof (unsigned char) * GetDimensions(0) * GetDimensions(1));
-
- /* Read LUT */
- fseek (fp, 1024, SEEK_SET);
- fread (pt_lut, sizeof(unsigned char), (GetDimensions(1)-1)*GetDimensions(0) / 4, fp);
-
- /* Read first row */
- for (i = 0; i < GetDimensions(0); i++) {
- fread (&a, sizeof(uint32_t), 1, fp);
- buf[i] = a;
- b = a;
+ GateAsciiHeader header;
+ if (!ReadHeader(handle,header)) {
+ itkGenericExceptionMacro(<< "Could not read header: " << m_FileName);
+ fclose(handle);
+ return;
}
- /* Read first pixel of second row */
- fread (&a, sizeof(uint32_t), 1, fp);
- buf[i++] = a;
- b = a;
-
- /* Decompress the rest */
- lut_idx = 0;
- lut_off = 0;
- while (i < GetDimensions(0) * GetDimensions(1)) {
- uint32_t r11, r12, r21;
-
- r11 = buf[i-GetDimensions(0)-1];
- r12 = buf[i-GetDimensions(0)];
- r21 = buf[i-1];
- v = pt_lut[lut_idx];
- switch (lut_off) {
- case 0:
- v = v & 0x03;
- lut_off ++;
- break;
- case 1:
- v = (v & 0x0C) >> 2;
- lut_off ++;
- break;
- case 2:
- v = (v & 0x30) >> 4;
- lut_off ++;
- break;
- case 3:
- v = (v & 0xC0) >> 6;
- lut_off = 0;
- lut_idx ++;
- break;
+ {
+ double* buffer = static_cast<double*>(abstract_buffer);
+ int read_count = 0;
+ while (true) {
+ std::string line;
+ if (!ReadLine(handle,line)) break;
+ *buffer = ConvertFromString<double>(line);
+ read_count++;
+ buffer++;
}
- switch (v) {
- case 0:
- num_read = fread (&dc, sizeof(unsigned char), 1, fp);
- if (num_read != 1) goto read_error;
- diff = dc;
- break;
- case 1:
- num_read = fread (&ds, sizeof(unsigned short), 1, fp);
- if (num_read != 1) goto read_error;
- diff = ds;
- break;
- case 2:
- num_read = fread (&dl, sizeof(uint32_t), 1, fp);
- if (num_read != 1) goto read_error;
- diff = dl;
- break;
- }
-
- buf[i] = r21 + r12 + diff - r11;
- b = buf[i];
- i++;
+ assert(read_count == header.nb_value);
}
- /* Clean up */
- free (pt_lut);
- fclose (fp);
- return;
-
-read_error:
-
- itkGenericExceptionMacro(<< "Error reading gate ascii file");
- free (pt_lut);
- fclose (fp);
- return;
+ fclose(handle);
}
//--------------------------------------------------------------------
bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite)
{
+ if (GetExtension(std::string(FileNameToWrite)) != "txt") return false;
+ return true;
+}
+
+void clitk::GateAsciiImageIO::WriteImageInformation()
+{
+ cout << GetNumberOfDimensions() << endl;
+}
+
+bool clitk::GateAsciiImageIO::SupportsDimension(unsigned long dim)
+{
+ if (dim==2) return true;
return false;
}
//--------------------------------------------------------------------
// Write Image
-void clitk::GateAsciiImageIO::Write(const void* buffer)
+void clitk::GateAsciiImageIO::Write(const void* abstract_buffer)
{
+ const unsigned long nb_value = GetDimensions(0)*GetDimensions(1);
+ std::stringstream stream;
+ stream << "######################" << endl;
+ stream << "# Matrix Size= (" << GetSpacing(0)*GetDimensions(0) << "," << GetSpacing(1)*GetDimensions(1) << ",1)" << endl;
+ stream << "# Resol = (" << GetDimensions(0) << "," << GetDimensions(1) << ",1)" << endl;
+ stream << "# VoxelSize = (" << GetSpacing(0) << "," << GetSpacing(1) << ",1)" << endl;
+ stream << "# nbVal = " << nb_value << endl;
+ stream << "######################" << endl;
+
+ if(this->GetComponentType()==itk::ImageIOBase::UCHAR) {
+ const unsigned char* buffer = static_cast<const unsigned char*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::CHAR) {
+ const char* buffer = static_cast<const char*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::USHORT) {
+ const unsigned short* buffer = static_cast<const unsigned short*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::SHORT) {
+ const short* buffer = static_cast<const short*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::UINT) {
+ const unsigned int* buffer = static_cast<const unsigned int*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::INT) {
+ const int* buffer = static_cast<const int*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::ULONG) {
+ const unsigned long* buffer = static_cast<const unsigned long*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::LONG) {
+ const long* buffer = static_cast<const long*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::FLOAT) {
+ const float* buffer = static_cast<const float*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else if(this->GetComponentType()==itk::ImageIOBase::DOUBLE) {
+ const double* buffer = static_cast<const double*>(abstract_buffer);
+ for (unsigned long kk=0; kk<nb_value; kk++)
+ stream << buffer[kk] << endl;
+ } else {
+ itkGenericExceptionMacro(<< "Unhandled pixel type: " << this->GetComponentTypeAsString(this->GetComponentType()));
+ return;
+ }
+
+ FILE* handle = fopen(m_FileName.c_str(),"w");
+ if (!handle) {
+ itkGenericExceptionMacro(<< "Could not open file (for writing): " << m_FileName);
+ return;
+ }
+
+ fwrite(stream.str().c_str(),1,stream.str().size(),handle);
+ fclose(handle);
}