/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "itkFreeSurferAsciiMeshIO.h" #include "itkMakeUniqueForOverwrite.h" #include "itksys/SystemTools.hxx" namespace itk { FreeSurferAsciiMeshIO::FreeSurferAsciiMeshIO() { this->AddSupportedWriteExtension(".fsa"); } FreeSurferAsciiMeshIO::~FreeSurferAsciiMeshIO() = default; bool FreeSurferAsciiMeshIO::CanReadFile(const char * fileName) { if (!itksys::SystemTools::FileExists(fileName, true)) { return false; } if (itksys::SystemTools::GetFilenameLastExtension(fileName) != ".fsa") { return false; } return true; } bool FreeSurferAsciiMeshIO::CanWriteFile(const char * fileName) { if (itksys::SystemTools::GetFilenameLastExtension(fileName) != ".fsa") { return false; } return true; } void FreeSurferAsciiMeshIO::OpenFile() { if (this->m_FileName.empty()) { itkExceptionMacro("No input FileName"); } if (!itksys::SystemTools::FileExists(m_FileName.c_str())) { itkExceptionMacro("File " << this->m_FileName << " does not exist"); } this->m_InputFile.open(this->m_FileName.c_str(), std::ios::in); if (!m_InputFile.is_open()) { itkExceptionMacro("Unable to open file " << this->m_FileName); } } void FreeSurferAsciiMeshIO::CloseFile() { if (m_InputFile.is_open()) { m_InputFile.close(); } } void FreeSurferAsciiMeshIO::ReadMeshInformation() { // Define input file stream and attach it to input file OpenFile(); // Read the ASCII file information constexpr int numberOfInfoLines = 1; constexpr unsigned int numberOfCellPoints = 3; std::string line; for (int ii = 0; ii < numberOfInfoLines; ++ii) { std::getline(m_InputFile, line); } this->m_FileType = IOFileEnum::ASCII; // Read the number of points and number of cells m_InputFile >> this->m_NumberOfPoints; m_InputFile >> this->m_NumberOfCells; this->m_PointDimension = 3; // If number of points is not equal zero, update points if (this->m_NumberOfPoints) { this->m_UpdatePoints = true; } // If number of cells is not equal zero, update points if (this->m_NumberOfCells) { this->m_UpdateCells = true; } // Set default point component type this->m_PointComponentType = IOComponentEnum::FLOAT; // Set default cell component type this->m_CellComponentType = IOComponentEnum::UINT; this->m_CellBufferSize = this->m_NumberOfCells * (numberOfCellPoints + 2); // Set default point pixel component and point pixel type this->m_PointPixelComponentType = IOComponentEnum::FLOAT; this->m_PointPixelType = IOPixelEnum::SCALAR; this->m_NumberOfPointPixelComponents = 1; // Set default cell pixel component and point pixel type this->m_CellPixelComponentType = IOComponentEnum::FLOAT; this->m_CellPixelType = IOPixelEnum::SCALAR; this->m_NumberOfCellPixelComponents = 1; } void FreeSurferAsciiMeshIO::ReadPoints(void * buffer) { // Number of data array auto * data = static_cast(buffer); // Read points m_InputFile.precision(12); float value; SizeValueType index = 0; for (SizeValueType id = 0; id < this->m_NumberOfPoints; ++id) { for (unsigned int ii = 0; ii < this->m_PointDimension; ++ii) { m_InputFile >> data[index++]; } m_InputFile >> value; } } void FreeSurferAsciiMeshIO::ReadCells(void * buffer) { // Get cell buffer m_InputFile.precision(12); SizeValueType index = 0; constexpr unsigned int numberOfCellPoints = 3; const auto data = make_unique_for_overwrite(this->m_NumberOfCells * numberOfCellPoints); float value; for (SizeValueType id = 0; id < this->m_NumberOfCells; ++id) { for (unsigned int ii = 0; ii < numberOfCellPoints; ++ii) { m_InputFile >> data[index++]; } m_InputFile >> value; } this->WriteCellsBuffer( data.get(), static_cast(buffer), CellGeometryEnum::TRIANGLE_CELL, 3, this->m_NumberOfCells); CloseFile(); } void FreeSurferAsciiMeshIO::ReadPointData(void * itkNotUsed(buffer)) {} void FreeSurferAsciiMeshIO::ReadCellData(void * itkNotUsed(buffer)) {} void FreeSurferAsciiMeshIO::WriteMeshInformation() { // Check file name if (this->m_FileName.empty()) { itkExceptionMacro("No Input FileName"); } // Write to output file std::ofstream outputFile(this->m_FileName.c_str()); if (!outputFile.is_open()) { itkExceptionMacro("Unable to open file\n" "outputFilename= " << this->m_FileName); } // Write FreeSurfer Surface file header outputFile << "#!ascii version of " << this->m_FileName << std::endl; // Write the number of points and number of cells outputFile << this->m_NumberOfPoints << " " << this->m_NumberOfCells << std::endl; outputFile.close(); } void FreeSurferAsciiMeshIO::WritePoints(void * buffer) { // check file name if (this->m_FileName.empty()) { itkExceptionMacro("No Input FileName"); } // Write to output file std::ofstream outputFile(this->m_FileName.c_str(), std::ios_base::app); if (!outputFile.is_open()) { itkExceptionMacro("Unable to open file\n" "outputFilename= " << this->m_FileName); } // Write points switch (this->m_PointComponentType) { case IOComponentEnum::UCHAR: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::CHAR: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::USHORT: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::SHORT: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::UINT: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::INT: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::ULONG: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::LONG: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::ULONGLONG: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::LONGLONG: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::FLOAT: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::DOUBLE: { WritePoints(static_cast(buffer), outputFile); break; } case IOComponentEnum::LDOUBLE: { WritePoints(static_cast(buffer), outputFile); break; } default: { itkExceptionMacro("Unknown point pixel component type" << std::endl); } } outputFile.close(); } void FreeSurferAsciiMeshIO::WriteCells(void * buffer) { // Check file name if (this->m_FileName.empty()) { itkExceptionMacro("No Input FileName"); } // Write to output file std::ofstream outputFile(this->m_FileName.c_str(), std::ios_base::app); if (!outputFile.is_open()) { itkExceptionMacro("Unable to open file\n" "outputFilename= " << this->m_FileName); } // Write triangles switch (this->m_CellComponentType) { case IOComponentEnum::UCHAR: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::CHAR: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::USHORT: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::SHORT: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::UINT: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::INT: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::ULONG: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::LONG: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::ULONGLONG: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::LONGLONG: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::FLOAT: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::DOUBLE: { WriteCells(static_cast(buffer), outputFile); break; } case IOComponentEnum::LDOUBLE: { WriteCells(static_cast(buffer), outputFile); break; } default: { itkExceptionMacro("Unknown cell pixel component type" << std::endl); } } outputFile.close(); } void FreeSurferAsciiMeshIO::WritePointData(void * itkNotUsed(buffer)) {} void FreeSurferAsciiMeshIO::WriteCellData(void * itkNotUsed(buffer)) {} void FreeSurferAsciiMeshIO::Write() {} void FreeSurferAsciiMeshIO::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); } } // namespace itk