// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #ifndef __clang_analyzer__ // VSA-7043 #include "pnm.hpp" namespace VideoStitch { namespace Util { bool PnmReader::read(const char *filename, int64_t &w, int64_t &h, std::vector<unsigned char> &data, std::ostream *err, bool pad) { std::ifstream ifs(filename, std::ifstream::in | std::ifstream::binary); if (!ifs.good()) { if (err) { *err << "Cannot open file '" << filename << "' for reading." << std::endl; } return false; } if (!read(ifs, w, h, data, err, pad)) { return false; } ifs.close(); return true; } bool PnmReader::read(std::ifstream &ifs, int64_t &w, int64_t &h, std::vector<unsigned char> &data, std::ostream *err, bool pad) { data.resize(0); char buf[bufSize]; ifs.getline(buf, bufSize); if (buf[0] != 'P') { if (err) { *err << "Not a PNM file." << std::endl; } return false; } switch (buf[1]) { case '1': return _read<AsciiPBM>(ifs, w, h, data, pad, err); case '2': return _read<AsciiPGM>(ifs, w, h, data, pad, err); case '3': return _read<AsciiPPM>(ifs, w, h, data, pad, err); case '4': return _read<BinPGM>(ifs, w, h, data, pad, err); // FIXME case '5': return _read<BinPGM>(ifs, w, h, data, pad, err); case '6': return _read<BinPPM>(ifs, w, h, data, pad, err); default: if (err) { *err << "Not a PNM file." << std::endl; } return false; } } bool PnmReader::_readCommentWidthHeight(std::ifstream &ifs, int64_t &width, int64_t &height, std::ostream *err) { // read comments char buf[bufSize]; while (ifs.peek() == '#') { ifs.getline(buf, bufSize); } ifs >> width; if (ifs.eof() || ifs.fail()) { if (err) { *err << "Cannot read PNM width." << std::endl; } return false; } ifs >> height; if (ifs.eof() || ifs.fail()) { if (err) { *err << "Cannot read PNM width." << std::endl; } return false; } int64_t depth; ifs >> depth; if (ifs.eof() || ifs.fail()) { if (err) { *err << "Cannot read PNM depth." << std::endl; } return false; } ifs.getline(buf, bufSize); // read the remaining of the line (\n) return true; } template <PnmReader::PixType type> bool PnmReader::_read(std::ifstream &ifs, int64_t &w, int64_t &h, std::vector<unsigned char> &data, bool pad, std::ostream *err) { if (!_readCommentWidthHeight(ifs, w, h, err)) { return false; } data.reserve((size_t)(w * h * (3 + (int)pad))); for (int64_t i = 0; i < w * h; ++i) { _readPixel<type>(ifs, data); if (pad) { data.push_back(255U); } } return true; } template <> void PnmReader::_readPixel<PnmReader::AsciiPBM>(std::ifstream &ifs, std::vector<unsigned char> &data) { unsigned v; ifs >> v; data.push_back(v ? 255U : 0); data.push_back(v ? 255U : 0); data.push_back(v ? 255U : 0); } template <> void PnmReader::_readPixel<PnmReader::AsciiPGM>(std::ifstream &ifs, std::vector<unsigned char> &data) { unsigned v; ifs >> v; data.push_back((unsigned char)v); data.push_back((unsigned char)v); data.push_back((unsigned char)v); } template <> void PnmReader::_readPixel<PnmReader::AsciiPPM>(std::ifstream &ifs, std::vector<unsigned char> &data) { unsigned v; ifs >> v; data.push_back((unsigned char)v); ifs >> v; data.push_back((unsigned char)v); ifs >> v; data.push_back((unsigned char)v); } template <> void PnmReader::_readPixel<PnmReader::BinPGM>(std::ifstream &ifs, std::vector<unsigned char> &data) { unsigned char v; ifs.read((char *)&v, 1); data.push_back(v); data.push_back(v); data.push_back(v); } template <> void PnmReader::_readPixel<PnmReader::BinPPM>(std::ifstream &ifs, std::vector<unsigned char> &data) { unsigned char v; ifs.read((char *)&v, 1); data.push_back(v); ifs.read((char *)&v, 1); data.push_back(v); ifs.read((char *)&v, 1); data.push_back(v); } std::ofstream *PpmWriter::openPpm(const char *filename, int64_t w, int64_t h, std::ostream *err) { std::ofstream *ofs = openGeneric(filename, err); if (ofs) { *ofs << "P6\n" << w << " " << h << "\n255\n"; } return ofs; } std::ofstream *PpmWriter::openPam(const char *filename, int64_t w, int64_t h, std::ostream *err) { std::ofstream *ofs = openGeneric(filename, err); if (ofs) { *ofs << "P7\nWIDTH " << w << "\nHEIGHT " << h << "\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n"; } return ofs; } std::ofstream *PpmWriter::openPgm(const char *filename, int64_t w, int64_t h, std::ostream *err) { std::ofstream *ofs = openGeneric(filename, err); if (ofs) { *ofs << "P5\n" << w << " " << h << "\n255\n"; } return ofs; } std::ofstream *PpmWriter::openGeneric(const char *filename, std::ostream *err) { std::ofstream *ofs = new std::ofstream(filename, std::ios_base::out | std::ios_base::binary); if (!ofs->good()) { if (err) { *err << "Cannot open file '" << filename << "' for writing." << std::endl; } delete ofs; ofs = NULL; } return ofs; } } // namespace Util } // namespace VideoStitch #endif // __clang_analyzer__