PNM 阅读器:无法以二进制模式读取某些文件

Posted

技术标签:

【中文标题】PNM 阅读器:无法以二进制模式读取某些文件【英文标题】:PNM Reader: Can't read some files in binary mode 【发布时间】:2013-05-27 21:38:54 【问题描述】:

我在处理 pnm 文件时遇到了一些问题(这很明显,否则我不会在这里发布 XD)。问题是,我的老师要求我们开发一个简单的二进制模式 pnm 阅读器,然后将其打印到屏幕上。我正在使用 libEGL(一个可用的框架here)。我的问题是它只适用于这两个图像,而其他任何一个都失败了。

使用 birch.pnm 和 checkers.pnm 可以正常工作,但大教堂.pnm、cotton.pnm 和 fish_tile.pnm 只是简单地进入无限循环或抛出错误。

图片可用here

我的代码如下:

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include "engcomp_glib.h"

using namespace std;

struct RGB
    char red, green, blue;
;

int main(int argc, char* argv[])
    RGB **image;
    RGB pixel;
//ifstream _file("..\\bin\\birch.pnm");
ifstream _file("..\\bin\\checkers.pnm");

//ifstream _file("..\\bin\\cotton.pnm");
//ifstream _file("..\\bin\\cathedral.pnm");
//ifstream _file("..\\bin\\fish_tile.pnm");
string type, maxColor;
int width, height;

if(_file)
    _file >> type;

    if(type != "P6")
        cout << "Error! File type is not allowed." << endl;

    _file >> width >> height >> maxColor;
    _file.close();

    egl_inicializar(width, height, true);
    image = new RGB *[height];

    for(int row = 0; row < height; row++)
        image[row] = new RGB[width];

    //Working 8D
    //_file.open("..\\bin\\birch.pnm", ios::binary);
    _file.open("..\\bin\\checkers.pnm", ios::binary);

    //Not working D:<
    //_file.open("..\\bin\\cathedral.pnm", ios::binary);
    //_file.open("..\\bin\\fish_tile.pnm", ios::binary);
    //_file.open("..\\bin\\cotton.pnm", ios::binary);

        //imagem img; img.carregar("..\\bin\\birch.pnm");

        _file.seekg(0, _file.end);

        int size = _file.tellg();
        int currentSize = 0, counter = 0;
        char byte;

        _file.seekg(0, _file.beg);

        do
            _file.read(reinterpret_cast<char *> (&byte), sizeof(char));

            if(byte == 10 || byte == 13)
                counter++;

        while(counter < 3);

        int rows = 0, columns = 0;

        while(size != currentSize)
            _file.read(reinterpret_cast<char *> (&pixel), sizeof(RGB));

            if(rows < height && columns < width)
                image[rows][columns] = pixel;
                rows++;
            
            else if(rows == height)
                rows = 0;
                columns++;

                image[rows][columns] = pixel;

                rows++;
            
            //else if(columns >= width)
                //currentSize = size;

            currentSize = _file.tellg();
        

        _file.close();

        while(!key[SDLK_ESCAPE])
            for(int row = 0; row < height; row++)
                for(int column = 0; column < width; column++)
                    //egl_pixel(row, column, image[row][column].red, image[row][column].green, image[row][column].blue);
                    egl_pixel(column, row, image[column][row].red, image[column][row].green, image[column][row].blue);
                    //img.desenha(0, 0);
            egl_desenha_frame(false);
        
    
    egl_finalizar();

    return 0;

这没有意义,因为它适用于其中两个,应该对它们都有效 我在文本编辑器中将它们全部打开,它们有标题,所以问题不存在。我究竟做错了什么?我的同事写了一个代码,将像素存储到一个大小为 [height * width] 的数组中,并且可以读取除了大教堂.pnm 之外的几乎所有图像。

感谢您的耐心和帮助:)

【问题讨论】:

【参考方案1】:

pnm 的规范规定标头中的值由 空格 分隔,通常是换行符,但它们也可以是空格或制表符(或其他我无法想到的东西)片刻 ;)。例如,大教堂文件有一个空格作为分隔符。

根据规范,您正在从上到下,从左到右,而不是从左到右,从上到下阅读文件。

如果你想真正正确,如果 maxColor 不小于 256,你应该阅读 shorts 而不是 chars。

你可以顺便在这里找到规格:

http://netpbm.sourceforge.net/doc/ppm.html

祝你好运!

【讨论】:

以上是关于PNM 阅读器:无法以二进制模式读取某些文件的主要内容,如果未能解决你的问题,请参考以下文章

使用FFI将二进制数据读取为Lua号

Python之文件操作

如何在 java 中读取二进制 .Chn 格式文件?

二进制数据的模式搜索

在 C/C++ 中快速读取多个文件的某些字节

Python——文件读取与写入