X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=common%2FclitkGateAsciiImageIO.cxx;h=dd47ef46b61d6b670eead939d387869c41a2273f;hb=13c3d27643a3200f3751ab3c391ba36a32a1293c;hp=aa785f6378eb192c33310a196ad880e4fb25832f;hpb=afb8bc7fe27981af21b4dc69bdbda00c6c33a350;p=clitk.git diff --git a/common/clitkGateAsciiImageIO.cxx b/common/clitkGateAsciiImageIO.cxx index aa785f6..dd47ef4 100644 --- a/common/clitkGateAsciiImageIO.cxx +++ b/common/clitkGateAsciiImageIO.cxx @@ -17,7 +17,11 @@ ===========================================================================**/ // std include -#include +#include +#include +#include +using std::cout; +using std::endl; // clitk include #include "clitkGateAsciiImageIO.h" @@ -26,150 +30,233 @@ // itk include #include +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; +} + //-------------------------------------------------------------------- // Read Image Information void clitk::GateAsciiImageIO::ReadImageInformation() { - itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName); - - - /* 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(this->GetMetaDataDictionary(), "dCTProjectionAngle", hnd.dCTProjectionAngle); - //itk::ExposeMetaData( this->GetMetaDataDictionary(), &(hnd.dCTProjectionAngle), "dCTProjectionAngle"); + FILE* handle = fopen(m_FileName.c_str(),"r"); + if (!handle) { + itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName); + return; + } + + 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 filenameext = GetExtension(filename); - if (filenameext != std::string("hnd")) return false; + std::string filename(FileNameToRead); + + { // 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; + + GateAsciiHeader header; + if (!ReadHeader(handle,header)) { fclose(handle); return false; } + fclose(handle); + } + + 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' || feof(handle)) { + line = stream.str(); + return true; + } + + stream << item; + } +} + +template +T ConvertFromString(const std::string& value) +{ + 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 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(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false; + + if(!FindRegularExpressionNextLine(regex, regexstr[1], handle)) return false; + header.matrix_size[0] = ConvertFromString(regex.match(1)); + header.matrix_size[1] = ConvertFromString(regex.match(2)); + header.matrix_size[2] = ConvertFromString(regex.match(3)); + + if(!FindRegularExpressionNextLine(regex, regexstr[2], handle)) return false; + header.resolution[0] = ConvertFromString(regex.match(1)); + header.resolution[1] = ConvertFromString(regex.match(2)); + header.resolution[2] = ConvertFromString(regex.match(3)); + + if(!FindRegularExpressionNextLine(regex, regexstr[3], handle)) return false; + header.voxel_size[0] = ConvertFromString(regex.match(1)); + header.voxel_size[1] = ConvertFromString(regex.match(2)); + header.voxel_size[2] = ConvertFromString(regex.match(3)); + + if(!FindRegularExpressionNextLine(regex, regexstr[4], handle)) return false; + header.nb_value = ConvertFromString(regex.match(1)); + + if(!FindRegularExpressionNextLine(regex, regexstr[0], handle)) return false; + 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) - itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName); - - 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; - } - - /* 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; - } - 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; + FILE* handle = fopen(m_FileName.c_str(),"r"); + if (!handle) { + itkGenericExceptionMacro(<< "Could not open file (for reading): " << m_FileName); + return; } - buf[i] = r21 + r12 + diff - r11; - b = buf[i]; - i++; - } - - /* Clean up */ - free (pt_lut); - fclose (fp); - return; + GateAsciiHeader header; + if (!ReadHeader(handle,header)) { + itkGenericExceptionMacro(<< "Could not read header: " << m_FileName); + fclose(handle); + return; + } -read_error: + { + double* buffer = static_cast(abstract_buffer); + int read_count = 0; + while (true) { + std::string line; + if (!ReadLine(handle,line)) break; + *buffer = ConvertFromString(line); + read_count++; + buffer++; + } + assert(read_count == header.nb_value); + } - itkGenericExceptionMacro(<< "Error reading gate ascii file"); - free (pt_lut); - fclose (fp); - return; + fclose(handle); } //-------------------------------------------------------------------- bool clitk::GateAsciiImageIO::CanWriteFile(const char* FileNameToWrite) { - return false; + 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; + + const double* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kk