2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * @author Bastien Doignies (bastien.doignies@liris.cnrs.fr)
22 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
26 * This file is part of the DGtal library.
29#include <boost/iostreams/filtering_stream.hpp>
34 inline static T getAs(const std::map<std::string, std::string>& fields, const std::string& key)
38 auto it = fields.find(key);
39 if (it == fields.end())
41 trace.error() << "SVOReader: No such field \"" << key << "\"" << std::endl;
45 if constexpr (std::is_same_v<T, std::string>)
51 std::istringstream iss(it->second);
56 trace.error() << "SVOReader: Can't convert \"" << key << "\" to desired type." << std::endl;
65 inline std::vector<T> getMultipleAs(const std::map<std::string, std::string>& fields, unsigned int count, const std::string& key)
67 std::vector<T> result;
69 auto it = fields.find(key);
70 if (it == fields.end())
72 trace.error() << "SVOReader: No such field \"" << key << "\"" << std::endl;
76 if constexpr (std::is_same_v<T, std::string>)
82 std::istringstream iss(it->second);
83 for (unsigned int i = 0; i < count; ++i)
86 result.push_back(tmp);
89 if (!iss.fail() && !iss.eof())
91 trace.error() << "SVOReader: Can't convert \"" << key << "\" to desired type." << std::endl;
98 template<typename Int, typename Stream>
99 Int readBinInt(Stream& stream, unsigned int count)
101 std::uint64_t value = 0;
103 for (size_t i = 0; i < count; ++i)
105 if (!stream.get(byte)) throw IOException{};
106 value |= static_cast<std::uint64_t>(byte) << (8 * i);
108 boost::endian::little_to_native_inplace(value);
109 return static_cast<Int>(value);
112 template <class Space>
113 DigitalSetByOctree<Space> SVOReader<Space>::importSVO(const std::string& filename)
115 std::ifstream file(filename.c_str(), std::ios::binary);
118 trace.warning() << "SVOReader: can't open file '" << filename << "'" << std::endl;
123 std::map<std::string, std::string> header;
124 while (std::getline(file, line))
126 if (!line.empty() && line.back() == '.') break;
128 auto split = line.find(":");
129 if (split == std::string::npos)
131 trace.warning() << "SVOReader: unrecognized line \"" << line << "\"" << std::endl;
135 std::string key = line.substr(0, split);
136 std::string val = line.substr(split + 1);
139 auto start = val.find_first_not_of(" \t\r\n");
140 auto end = val.find_last_not_of(" \t\r\n");
141 if (start == std::string::npos)
143 trace.error() << "SVOReader: invalid value for line \"" << line << "\"" << std::endl;
144 throw DGtal::IOException{};
147 header[key] = val.substr(start, end - start + 1);
150 const std::string format = getAs<std::string>(header, "Format");
151 // const std::int32_t version = getAs<std::int32_t>(header, "Version");
152 const std::int32_t compress = getAs<std::int32_t>(header, "Compression");
153 const std::int32_t dim = getAs<std::int32_t>(header, "Dim");
154 const std::int32_t state = getAs<std::int32_t>(header, "State");
155 const std::uint64_t size = getAs<std::uint64_t>(header, "Size");
157 if (dim != Space::dimension)
159 trace.error() << "SVOReader: Dimension mismatch, space is " << Space::dimension << "d and Octree is " << dim << "d" << std::endl;
163 const auto lbdata = getMultipleAs<std::int64_t>(header, dim, "LowerBound");
164 const auto ubdata = getMultipleAs<std::int64_t>(header, dim, "UpperBound");
166 typename Space::Point lb, ub;
167 for (unsigned int i = 0; i < dim; ++i)
173 Octree octree(typename Octree::Domain(lb, ub));
174 octree.mySize = size;
175 octree.myState = static_cast<typename Octree::State>(state);
177 boost::iostreams::filtering_istream main;
178 if (compress) main.push(boost::iostreams::zlib_decompressor());
181 const int64_t sizesize = readBinInt<int64_t>(main, sizeof(int64_t));
182 const int64_t cellsize = readBinInt<int64_t>(main, sizeof(int64_t));
184 using CellI = typename Octree::CellIndex;
185 using Size = typename Octree::Size;
187 if (sizesize > sizeof(Size))
188 trace.warning() << "SVOReader: integer size mismatch, this may cause unwanted truncation" << std::endl;
190 if (cellsize > sizeof(CellI))
191 trace.warning() << "SVOReader: integer size mismatch, this may cause unwanted truncation" << std::endl;
194 octree.myNodes.resize(readBinInt<Size>(main, sizesize));
195 for (size_t i = 0; i < octree.myNodes.size(); ++i)
196 octree.myNodes[i].resize(readBinInt<Size>(main, sizesize));
200 for (size_t i = 0; i < octree.myNodes.size(); ++i)
201 for (size_t j = 0; j < octree.myNodes[i].size(); ++j)
202 for (unsigned int k = 0; k < Octree::CELL_COUNT; ++k)
203 octree.myNodes[i][j].children[k] = readBinInt<CellI>(main, cellsize);
207 trace.error() << "SVOReader: Unexpected EOF while reading data." << std::endl;