ifstream.read 只读了一半的文件
ifstream.read only reads half the file
我正在尝试制作一个简单的图像转换器(将 ppm 格式转换为自定义格式),但我在使用 ifstream.read 方法时遇到了问题。尽管有这个:
int rows,cols, maxV;
char header [100], *ptr;
std::ifstream im;
//open image in binary format
im.open(name.c_str(), std::ios::in | std::ios::binary);
if (!im)
{
std::cout << "Can't read image!" << std::endl;
exit(1);
}
//read the header of the image
im.getline(header, 3,'\n');
//test if header is P6
if ((header[0] != 80) || (header[1] != 54))
{
std::cout << "Image" << name << "is not .ppm format" << std::endl;
}
//get next line for height and width
im.getline(header,100,'\n');
//dont read the comments
while (header[0] == '#')
im.getline(header,100,'\n');
//number of columns, rows
cols = strtol(header, &ptr, 0);
rows = strtol(header, &ptr, 0);
maxV = strtol(header, &ptr, 0);
const int rows1=rows;
const int cols1=cols;
Component * tbuffer;
const_cast<Component*> (tbuffer);
tbuffer = new Component[rows1*cols1 * 3];
im.read((char *)tbuffer, cols*rows * 3);
std::cout << tbuffer[3000000] << std::endl;
im.close();
它只读取了我尝试读取的 4.320.000 个图像中的 2.700.007 个元素。所以 tbuffer[3.000.000] 将 "cout" NULL。我错过了什么吗?
编辑:关于组件:
typedef unsigned char Component;
Edit2:图像为 1200*1200(列*行)。
2.700.007 是 tbuffer 的最后一个索引,其中有一个值。 tbuffer 的其余部分保持为空
您阅读的 PPM format 不保证幻数 P6 后跟一个换行符,也不保证 header 的其余部分后跟一个换行符,也不保证长度, heigth 和 maxV 在同一条线上。
但是你的主要问题是
cols = strtol(header, &ptr, 0); // you start at the begin of the header
rows = strtol(header, &ptr, 0); // you start again at the begin of the header
maxV = strtol(header, &ptr, 0); // and another time !!
因此您的行和 maxV 可能不是文件中的值。你应该——不管上面提到的其他变化——而是使用:
cols = strtol(header, &ptr, 0); // you start at the begin of the header
rows = strtol(ptr, &ptr, 0); // continue after the first number
maxV = strtol(ptr, &ptr, 0); // ...
但也请记住,您不应该假设这三者在同一条线上。并且可能会有其他意见。
我建议您使用以下实用函数来根据 PPM 格式跳过空格和注释:
ifstream& skipwcmt(ifstream& im) {
char c;
do {
while ((c = im.get()) != EOF && isspace(c)) ;
if (isdigit(c))
im.unget();
else if (c == '#')
while ((c = im.get()) != EOF && c != '\n' && c != '\r');
} while (isspace(im.peek()));
return im;
}
您可以使用此函数阅读 header,如下所示:
// ...
// check magic number
im.read(header, 2);
if ((header[0] != 'P') || (header[1] != '6'))
{
std::cout << "Image" << name << "is not .ppm format" << std::endl;
exit(1);
}
skipwcmt(im) >> cols;
skipwcmt(im) >> rows;
skipwcmt(im) >> maxV;
if (!isspace(im.get())) { // folowed by exactly one whitespace !
std::cout << "Image" << name << "has a corrupted header" << std::endl;
exit(1);
}
// display the header to check the data
cout << "cols=" << cols << ", rows=" << rows << ", maxcol=" << maxV << endl;
备注:不知道你要看的文件是否保证maxV<=255。理论上,您可以拥有高达 65535 的值,在这种情况下,您需要为颜色组件读取 2 个字节而不是一个字节。
我正在尝试制作一个简单的图像转换器(将 ppm 格式转换为自定义格式),但我在使用 ifstream.read 方法时遇到了问题。尽管有这个:
int rows,cols, maxV;
char header [100], *ptr;
std::ifstream im;
//open image in binary format
im.open(name.c_str(), std::ios::in | std::ios::binary);
if (!im)
{
std::cout << "Can't read image!" << std::endl;
exit(1);
}
//read the header of the image
im.getline(header, 3,'\n');
//test if header is P6
if ((header[0] != 80) || (header[1] != 54))
{
std::cout << "Image" << name << "is not .ppm format" << std::endl;
}
//get next line for height and width
im.getline(header,100,'\n');
//dont read the comments
while (header[0] == '#')
im.getline(header,100,'\n');
//number of columns, rows
cols = strtol(header, &ptr, 0);
rows = strtol(header, &ptr, 0);
maxV = strtol(header, &ptr, 0);
const int rows1=rows;
const int cols1=cols;
Component * tbuffer;
const_cast<Component*> (tbuffer);
tbuffer = new Component[rows1*cols1 * 3];
im.read((char *)tbuffer, cols*rows * 3);
std::cout << tbuffer[3000000] << std::endl;
im.close();
它只读取了我尝试读取的 4.320.000 个图像中的 2.700.007 个元素。所以 tbuffer[3.000.000] 将 "cout" NULL。我错过了什么吗?
编辑:关于组件:
typedef unsigned char Component;
Edit2:图像为 1200*1200(列*行)。 2.700.007 是 tbuffer 的最后一个索引,其中有一个值。 tbuffer 的其余部分保持为空
您阅读的 PPM format 不保证幻数 P6 后跟一个换行符,也不保证 header 的其余部分后跟一个换行符,也不保证长度, heigth 和 maxV 在同一条线上。
但是你的主要问题是
cols = strtol(header, &ptr, 0); // you start at the begin of the header
rows = strtol(header, &ptr, 0); // you start again at the begin of the header
maxV = strtol(header, &ptr, 0); // and another time !!
因此您的行和 maxV 可能不是文件中的值。你应该——不管上面提到的其他变化——而是使用:
cols = strtol(header, &ptr, 0); // you start at the begin of the header
rows = strtol(ptr, &ptr, 0); // continue after the first number
maxV = strtol(ptr, &ptr, 0); // ...
但也请记住,您不应该假设这三者在同一条线上。并且可能会有其他意见。
我建议您使用以下实用函数来根据 PPM 格式跳过空格和注释:
ifstream& skipwcmt(ifstream& im) {
char c;
do {
while ((c = im.get()) != EOF && isspace(c)) ;
if (isdigit(c))
im.unget();
else if (c == '#')
while ((c = im.get()) != EOF && c != '\n' && c != '\r');
} while (isspace(im.peek()));
return im;
}
您可以使用此函数阅读 header,如下所示:
// ...
// check magic number
im.read(header, 2);
if ((header[0] != 'P') || (header[1] != '6'))
{
std::cout << "Image" << name << "is not .ppm format" << std::endl;
exit(1);
}
skipwcmt(im) >> cols;
skipwcmt(im) >> rows;
skipwcmt(im) >> maxV;
if (!isspace(im.get())) { // folowed by exactly one whitespace !
std::cout << "Image" << name << "has a corrupted header" << std::endl;
exit(1);
}
// display the header to check the data
cout << "cols=" << cols << ", rows=" << rows << ", maxcol=" << maxV << endl;
备注:不知道你要看的文件是否保证maxV<=255。理论上,您可以拥有高达 65535 的值,在这种情况下,您需要为颜色组件读取 2 个字节而不是一个字节。