用Java读取pgm文件

时间:2012-08-12 12:40:32

标签: java pgm

我需要读取一个pgm文件并将其中包含的值数组存储在2D数组中。 在PGM格式中,每个像素由0和MaxVal之间的灰度值指定。前三行提供与图像相关的信息:幻数,高度,宽度和maxVal。该文件还包括空格。以#开头的行是注释。 这就是我到现在所写的。

public class PGM{

public static void main(String args[]) throws Exception {
    FileInputStream f = new FileInputStream("C:\\......\\brain_001.pgm");
    DataInputStream d = new DataInputStream(f);
    d.readLine();//first line contains P5
    String line = d.readLine();//second line contains height and width
    Scanner s = new Scanner(line);
    int width = s.nextInt();
    int height = s.nextInt();
    line = d.readLine();//third line contains maxVal
    s = new Scanner(line);
    int maxVal = s.nextInt();
    byte[][] im = new byte[height][width];
    for (int i = 0; i < 258; i++) {
        for (int j = 0; j < 258; j++) {
            im[i][j] = -1;
        }
    }
    int count = 0;
    byte b;
    try {
        while (true) {
            b = (byte) (d.readUnsignedByte());
            if (b == '\n') { //do nothing if new line encountered
            } else if (b == '#') {
                d.readLine();
            } else if (Character.isWhitespace(b)) { // do nothing if whitespace encountered
            } else {
                im[count / width][count % width] = b;
                count++;
            }
        }
    } catch (EOFException e) {
    }
    System.out.println("Height=" + height);
    System.out.println("Width=" + height);
    System.out.println("Required elemnts=" + (height * width));
    System.out.println("Obtained elemnets=" + count);

}
}

运行程序时,我得到以下输出:

Height=258
Width=258
Required elemnts=66564
Obtained elemnets=43513

元素的数量(每个对应于灰度值)小于所需的元素数量。当我用PGM查看器打开文件时,一切都正确显示。 此外,当我打印数组的内容时,我看到很多负值。但所有这些都必须大于或等于零。 我哪里出错?

2 个答案:

答案 0 :(得分:1)

很可能是因为readLine()中已弃用的方法DataInputStream。如其注释中所述

*此方法无法将字节正确转换为字符。从JDK 1.1开始,读取文本行的首选方法是通过BufferedReader.readLine()方法。使用DataInputStream类读取行的程序可以通过替换表单的代码转换为使用BufferedReader类:      DataInputStream d = new DataInputStream(in);

使用:      BufferedReader d           = new BufferedReader(new InputStreamReader(in)); *

当我根据这个建议更改你的程序时,它对我有用(我做了其他一些改动:

更新以处理PGM的P2和P5风格

    public static void main(String args[]) throws Exception {
        try {
            InputStream f = ClassLoader.getSystemClassLoader().getResourceAsStream("lena.pgm");
            BufferedReader d = new BufferedReader(new InputStreamReader(f));
            String magic = d.readLine();    // first line contains P2 or P5
            String line = d.readLine();     // second line contains height and width
            while (line.startsWith("#")) {
                line = d.readLine();
            }
            Scanner s = new Scanner(line);
            int width = s.nextInt();
            int height = s.nextInt();
            line = d.readLine();// third line contains maxVal
            s = new Scanner(line);
            int maxVal = s.nextInt();
            byte[][] im = new byte[height][width];

            int count = 0;
            int b = 0;
            try {
                while (count < height*width) {
                    b = d.read() ;
                    if ( b < 0 ) 
                        break ;

                    if (b == '\n') { // do nothing if new line encountered
                    } 
//                  else if (b == '#') {
//                      d.readLine();
//                  } 
//                  else if (Character.isWhitespace(b)) { // do nothing if whitespace encountered
//                  } 
                    else {
                        if ( "P5".equals(magic) ) { // Binary format
                            im[count / width][count % width] = (byte)((b >> 8) & 0xFF);
                            count++;
                            im[count / width][count % width] = (byte)(b & 0xFF);
                            count++;
                        }
                        else {  // ASCII format
                            im[count / width][count % width] = (byte)b ;
                            count++;
                        }
                    }
                }
            } catch (EOFException eof) {
                eof.printStackTrace(System.out) ;
            }
            System.out.println("Height=" + height);
            System.out.println("Width=" + height);
            System.out.println("Required elements=" + (height * width));
            System.out.println("Obtained elements=" + count);
        }
        catch(Throwable t) {
            t.printStackTrace(System.err) ;
            return ;
        }

    }

答案 1 :(得分:0)

以下代码适用于我:

FileInputStream f;
    try {
        f = new FileInputStream(fileLocation);
        BufferedReader br = new BufferedReader(new InputStreamReader(f));
        String magic = br.readLine();    // first line contains P2 or P5
        String line = br.readLine();     // second line contains height and width

        //-scan width and height
        Scanner s = new Scanner(line);
        int width = s.nextInt();
        int height = s.nextInt();
        s.close();

        //-scan max value
        line = br.readLine();// third line contains maxVal
        s = new Scanner(line);
        //          int maxVal = s.nextInt();
        //-close scanner
        s.close();
        //-close buffer
        br.close();
        f.close();

        xvec=new DenseMatrix64F(height*width, 1);

        int b=0;
        int counter=0;
        f = new FileInputStream(fileLocation);
        DataInputStream dis = new DataInputStream(f);
        //-move across unused lines
        dis.readLine();
        dis.readLine();
        dis.readLine();
        while ((b=dis.read()) >= 0) {
            xvec.set(counter, 0, b);
            counter++;
        }
        dis.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }