24 #ifndef DUMUX_RASTER_IMAGE_READER_HH
25 #define DUMUX_RASTER_IMAGE_READER_HH
37 #include <dune/common/exceptions.hh>
75 class Result :
private std::vector<T>
77 using Parent = std::vector<T>;
93 : Parent(std::move(data))
94 , header_(std::move(
header))
101 using Parent::operator[];
117 static const auto format = []{
118 std::map<std::string, Format> format;
119 format[
"P1"] =
Format{
"P1",
"Portable BitMap",
"ASCII"};
120 format[
"P2"] =
Format{
"P2",
"Portable GrayMap",
"ASCII"};
121 format[
"P3"] =
Format{
"P3",
"Portable PixMap",
"ASCII"};
122 format[
"P4"] =
Format{
"P4",
"Portable BitMap",
"binary"};
123 format[
"P5"] =
Format{
"P5",
"Portable GrayMap",
"binary"};
124 format[
"P5"] =
Format{
"P5",
"Portable PixMap",
"binary"};
128 if (!format.count(magicNumber))
129 DUNE_THROW(Dune::IOError, magicNumber <<
" is not a valid magic number for the Netpbm format");
131 return format.at(magicNumber);
144 std::ifstream infile(fileName, std::ios::binary);
147 DUNE_THROW(Dune::IOError,
"Raster data file not found or corrupt");
150 std::vector<bool> values;
153 values = readPBMDataASCII_(infile, headerData);
155 values = readPBMDataBinary_(infile, headerData);
157 DUNE_THROW(Dune::IOError, headerData.
format.
magicNumber <<
" not supported. Use readPBM for P1 and P4 or readPGM for P2 and P5");
159 Result<bool> result(std::move(values), std::move(headerData));
162 if (useDuneGridOrdering)
180 template<
class ValueType = std::u
int8_t>
183 std::ifstream infile(fileName, std::ios::binary);
186 DUNE_THROW(Dune::IOError,
"Raster data file not found or corrupt");
189 std::vector<ValueType> values;
192 values = NetPBMReader::template readPGMDataASCII_<ValueType>(infile, headerData);
194 values = NetPBMReader::template readPGMDataBinary_<ValueType>(infile, headerData);
196 DUNE_THROW(Dune::IOError, headerData.
format.
magicNumber <<
" not supported. Use readPBM for P1 and P4 or readPGM for P2 and P5");
201 if (useDuneGridOrdering)
215 std::string inputLine;
218 std::getline(infile, inputLine);
223 while (!infile.eof())
225 std::getline(infile, inputLine);
227 auto isComment = [](
const auto& s)
228 {
return (s.find(
"#") != std::string::npos); };
231 if (isComment(inputLine))
235 headerData.
nCols = std::stoi(inputLine.substr(0, inputLine.find(
" ")));
236 headerData.
nRows = std::stoi(inputLine.substr(inputLine.find(
" ") + 1));
239 if (magicNumber !=
"P1" && magicNumber !=
"P4")
241 std::getline(infile, inputLine);
242 headerData.
maxValue = std::stoi(inputLine);
259 for (std::size_t i = 0; i < result.size(); i += result.
header().nCols)
260 std::swap_ranges((result.begin() + i), (result.begin() + i + result.
header().
nCols), (tmp.end() - i - result.
header().
nCols));
272 std::cout <<
"Reading " << format.
type <<
" file (" << format.
encoding <<
")" << std::endl;
274 std::cout <<
"Maximum value : " << result.
header().
maxValue << std::endl;
284 template<
class Image,
class T>
289 using RowType = std::decay_t<
decltype(image[0])>;
290 image.resize(nRows, RowType(nCols));
292 std::size_t rowIdx = 0;
293 std::size_t colIdx = 0;
294 for (
const auto& val : result)
296 image[rowIdx][colIdx] = val;
299 if (++colIdx == nCols)
312 template<
class Image>
315 using OutputValueType = std::decay_t<
decltype(image[0][0])>;
317 std::vector<OutputValueType> data;
318 data.reserve(image.size()*image[0].size());
319 for (
const auto& row: image)
320 for (
const auto& col : row)
335 static std::vector<bool> readPBMDataASCII_(std::ifstream& infile,
336 const HeaderData& headerData)
338 std::string inputLine;
339 std::vector<bool> data;
340 data.reserve(numPixel_(headerData));
342 while (!infile.eof())
344 std::getline(infile, inputLine);
345 inputLine.erase(std::remove(inputLine.begin(), inputLine.end(),
'\n'), inputLine.end());
346 inputLine.erase(std::remove(inputLine.begin(), inputLine.end(),
' '), inputLine.end());
347 if (!inputLine.empty())
349 for (
const auto& value : inputLine)
351 assert(value ==
'0' || value ==
'1');
352 data.push_back(value -
'0');
368 static std::vector<bool> readPBMDataBinary_(std::ifstream& infile,
369 const HeaderData& headerData)
371 std::vector<bool> data(numPixel_(headerData));
373 std::size_t nBytes = 0;
374 std::size_t bitIndex = 0;
375 using Bit = std::uint8_t;
377 for (std::size_t j = 0; j < headerData.nRows; j++)
379 for (std::size_t i = 0; i < headerData.nCols; i++)
384 infile.read(&tmp, 1);
385 b =
static_cast<Bit
>(tmp);
387 DUNE_THROW(Dune::IOError,
"Failed reading byte " << nBytes);
392 const Bit k = 7 - (i % 8);
393 data[bitIndex++] =
static_cast<bool>((b >> k) & 1);
412 template<
class ValueType = std::u
int8_t>
413 static std::vector<ValueType> readPGMDataASCII_(std::ifstream& infile,
414 const HeaderData& headerData)
416 std::string inputLine;
418 std::vector<ValueType> data;
419 data.reserve(numPixel_(headerData));
421 while (!infile.eof())
423 std::getline(infile, inputLine);
424 if (inputLine.empty())
428 if (inputLine.find(
" ") != std::string::npos)
430 std::istringstream iss(inputLine);
431 std::vector<std::string> tokens;
432 std::copy(std::istream_iterator<std::string>(iss),
433 std::istream_iterator<std::string>(),
434 std::back_inserter(tokens));
436 for (
const auto& t : tokens)
437 data.push_back(std::stoi(t));
440 data.push_back(std::stoi(inputLine));
458 template<
class ValueType = std::u
int8_t>
459 static std::vector<ValueType> readPGMDataBinary_(std::ifstream& infile,
460 const HeaderData& headerData)
462 std::string inputLine;
465 const auto curPos = infile.tellg();
466 infile.seekg(0, std::ios::end);
467 const auto endPos = infile.tellg();
468 const auto size = endPos - curPos;
469 if (size != numPixel_(headerData))
470 DUNE_THROW(Dune::IOError,
"Binary file size does not match with raster image size");
473 infile.seekg(curPos, std::ios::beg);
476 std::vector<std::uint8_t> data(size);
477 infile.read(
reinterpret_cast<char*
>(&data[0]), size);
480 return std::vector<ValueType>(data.begin(), data.end());
488 static std::size_t numPixel_(
const HeaderData& headerData)
490 return headerData.nRows*headerData.nCols;
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
A simple reader class for the Netpbm format (https://en.wikipedia.org/wiki/Netpbm_format)....
Definition: rasterimagereader.hh:47
static HeaderData readHeader(std::ifstream &infile)
Returns the header data of the image file.
Definition: rasterimagereader.hh:212
static void fillImage(Image &image, const Result< T > &result)
Fill a pre-defined 2D image object, e.g. std::vector<std::vector<bool>>, with the pixel values stored...
Definition: rasterimagereader.hh:285
static Format getFormat(const std::string &magicNumber)
A helper function to retrieve the format data from a given magic number.
Definition: rasterimagereader.hh:115
static Result< bool > readPBM(const std::string &fileName, const bool useDuneGridOrdering=true)
Reads a *pbm (black and white) in ASCII or binary encoding. Returns a struct that contains both the p...
Definition: rasterimagereader.hh:142
static auto flattenImageToVector(const Image &image)
Flattens a 2D image object to a 1D container.
Definition: rasterimagereader.hh:313
static void applyDuneGridOrdering(Result< T > &result)
Change the ordering of the pixels according to Dune's convention, shifting the origin from upper left...
Definition: rasterimagereader.hh:256
static Result< ValueType > readPGM(const std::string &fileName, const bool useDuneGridOrdering=true)
Reads a *.pgm (grayscale) in ASCII or binary encoding. Returns a struct that contains both the pixel ...
Definition: rasterimagereader.hh:181
static void printInfo(const Result< T > &result)
Print the data contained in the header.
Definition: rasterimagereader.hh:269
A struct that holds all information of the image format.
Definition: rasterimagereader.hh:53
std::string encoding
Definition: rasterimagereader.hh:56
std::string magicNumber
Definition: rasterimagereader.hh:54
std::string type
Definition: rasterimagereader.hh:55
A struct that contains all header data of the image.
Definition: rasterimagereader.hh:63
Format format
Definition: rasterimagereader.hh:64
std::size_t maxValue
Definition: rasterimagereader.hh:67
std::size_t nCols
Definition: rasterimagereader.hh:65
std::size_t nRows
Definition: rasterimagereader.hh:66
The return type of the reading functions. Holds the actual pixel values and the header data.
Definition: rasterimagereader.hh:76
const HeaderData & header() const
Returns the header data.
Definition: rasterimagereader.hh:98
Result(const std::vector< T > &data, const HeaderData &header)
Contruct from data and header by copy.
Definition: rasterimagereader.hh:84
Result(std::vector< T > &&data, HeaderData &&header)
Contruct from data and header by move.
Definition: rasterimagereader.hh:92