如何在c++中从pgm文件中读取数据
How to read in data from a pgm file in C++
到目前为止,我可以读取每行并将其打印到控制台:
void readFile(){
string line;
ifstream myfile("example1.pgm");
if (myfile.is_open()){
while (myfile.good()){
getline (myfile,line);
cout << line;
}
}
然而,pgm文件显然总是在数据开始前有以下内容:
P2
# test.pgm
24 7
15
我如何调整我的代码,使它检查"P2"是存在的,忽略任何注释(#),并存储变量和随后的像素数据?
我有点迷路了,不熟悉c++,所以任何帮助都很感激。
谢谢
解析文件有很多不同的方法。对于这样的问题,你可以看看这个网站上的答案。个人而言,我会使用getline()循环并测试/解析每一行(存储在变量"line"中),您也可以使用stringstream,因为它更容易与多个值一起使用:
<<h2>想法/h2>第一行:测试P2 (Portable graymap)是否存在,可能使用类似
的内容if(line.compare("P2")) ...
第二行:什么都不做,你可以继续下一个getline()
第三行:存储图像的大小;对于stringstream,你可以这样做
int w,h;
ss >> w >> h;
以下行:存储像素数据,直到到达文件末尾
生成的代码
你可以试试下面的代码,并根据你的需要修改它:
#include <iostream> // cout, cerr
#include <fstream> // ifstream
#include <sstream> // stringstream
using namespace std;
int main() {
int row = 0, col = 0, numrows = 0, numcols = 0;
ifstream infile("file.pgm");
stringstream ss;
string inputLine = "";
// First line : version
getline(infile,inputLine);
if(inputLine.compare("P2") != 0) cerr << "Version error" << endl;
else cout << "Version : " << inputLine << endl;
// Second line : comment
getline(infile,inputLine);
cout << "Comment : " << inputLine << endl;
// Continue with a stringstream
ss << infile.rdbuf();
// Third line : size
ss >> numcols >> numrows;
cout << numcols << " columns and " << numrows << " rows" << endl;
int array[numrows][numcols];
// Following lines : data
for(row = 0; row < numrows; ++row)
for (col = 0; col < numcols; ++col) ss >> array[row][col];
// Now print the array to see the result
for(row = 0; row < numrows; ++row) {
for(col = 0; col < numcols; ++col) {
cout << array[row][col] << " ";
}
cout << endl;
}
infile.close();
}
编辑
简化PNM (PBM/PGM/PPM)报头处理的一种方法是逐行构建报头字符串,直到捕获了所有必需的数据。这并不需要太多的代码,只使用标准的c++库…
#include <string>
#include <iostream>
#include <sstream>
#include <stdexcept>
...
std::string header, magic;
int width=0, height=0, maxsample=0, samples=0, bits=0, bytes=0;
do {
try { getline(is,magic); } catch ( const std::ios_base::failure & ) {}
if ( !magic.empty() && magic[0] != '#' ) header += magic+" ";
if ( !( std::stringstream(header+" 1") >> magic >> width >> height >> maxsample ).eof() ) break;
if ( ( (magic=="P1"||magic=="P4") && maxsample==1 ) || !is.good() ) break;
} while ( true );
samples = magic=="P1"?1:magic=="P2"?1:magic=="P3"?3:magic=="P4"?1:magic=="P5"?1:magic=="P6"?3:0;
bits = (magic=="P1"||magic=="P4")?1:maxsample<256?8:maxsample<256*256?16:0, bytes = (width*samples*bits+7)>>3;
if ( width<=0 || height<=0 || maxsample<=0 || samples<=0 || bits<=0 ) throw std::runtime_error("invalid PNM header");
这处理注释(如果存在)和PBM的特殊情况(没有'maxsample'),并且无论是否在输入流上启用异常,它都可以工作。
一旦你读了头,读取图像数据通常是一件简单的事情,因为格式被定义为只是一个顺序的数据转储(可能是ASCII或二进制取决于'magic'值)。在16位二进制编码样本的情况下,格式规范指出"最重要的字节是第一个"(大端),因此这种情况可能需要一些特定于平台的处理。
如前所述,这需要c++ 11——可能是因为我使用stringstream
作为临时的方式。
一个警告:在一个病态的情况下,这可能会浪费大量的时间/RAM,而试图读取一个无效的头——因为getline
调用不是固有的边界。有一个相对简单的解决方案(用更健壮的东西替换getline
),但它需要更多的代码。
对于生产质量的应用程序,考虑使用libnetpbm。
- 正在将csv文件读取为双精度矢量
- 将从格式化文本文件读取的文本数据存储到链表
- C++ 读取文件读取文件不正确
- 使用对象文件读取三角形数据网格
- 如何减慢从 BVH 文件读取的 opengl 动画?
- 从文件读取,并写入函数C++中的数组
- 从对象C++中的文件读取内容时出现分段错误
- 从文件读取并通过矢量输出到控制台
- 尝试将字符串从文件读取到无符号字符向量中
- 如何将文本文件读取到二维数组中并以 c++ 打印
- 简化文件读取的函数
- 如何将逗号分隔的文件读取为 2D int 数组?
- 在 c++ 中将数据从文件读取到队列中
- 'std::wstring_convert'尽可能多地转换(从 UTF8 文件读取块)
- C++,从文件读取到结构,然后读取到向量(结构被推入向量太多次,而不仅仅是一次)
- 文件读取C++包括空格键
- 从文件读取时未将值推回矢量
- 从文件 C++ 读取时的无限循环
- 从同一文件读取和写入?
- 从.txt文件读取到C++中的双精度向量