ifstream.read只读取文件的一半

时间:2015-01-31 17:12:58

标签: c++ file ifstream

我正在尝试制作一个简单的图像转换器(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(cols *行)。 2.700.007是tbuffer的最后一个索引,其中包含一个值。 tbuffer的其余部分仍然是空的

1 个答案:

答案 0 :(得分:0)

您阅读的PPM format并不保证幻数P6后面跟一个换行符,也不保证标题的其余部分后跟换行符,也不保证lentgh,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;
}

您可以使用此功能读取标题,如下所示:

// ...
// 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&lt; = 255。理论上,您可以使用高达65535的值,在这种情况下,您需要为颜色组件而不是一个读取2个字节。