The problem with your code is that you are using the wrong class to read raw data from the file. As the BufferedReader
documentation says:
public int read() throws IOException
Reads a single character.
Returns: The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached
So each call to the read()
method of BufferedReader
actually consumes one or two bytes (based on character encoding) from the input stream, which is not what you want. This also explains why you get a lot of -1: the stream ended much earlier than you thought.
Since PGM contains values as ASCII decimal, it is easy to parse using the Scanner class.
Here's an almost untested code that shows how to read a PGM image assuming that:
- it contains a single comment after the magic number (i.e. it does not have lines that start with a # except the second one)
- the PGM file is exactly 4 lines long.
Here's the code:
String filePath = "image.pgm";
fileInputStream = new FileInputStream(filePath);
Scanner scan = new Scanner(fileInputStream);
// Discard the magic number
scan.nextLine();
// Discard the comment line
scan.nextLine();
// Read pic width, height and max value
int picWidth = scan.nextInt();
int picHeight = scan.nextInt();
int maxvalue = scan.nextInt();
fileInputStream.close();
// Now parse the file as binary data
fileInputStream = new FileInputStream(filePath);
DataInputStream dis = new DataInputStream(fileInputStream);
// look for 4 lines (i.e.: the header) and discard them
int numnewlines = 4;
while (numnewlines > 0) {
char c;
do {
c = (char)(dis.readUnsignedByte());
} while (c != '\n');
numnewlines--;
}
// read the image data
int[][] data2D = new int[picHeight][picWidth];
for (int row = 0; row < picHeight; row++) {
for (int col = 0; col < picWidth; col++) {
data2D[row][col] = dis.readUnsignedByte();
System.out.print(data2D[row][col] + " ");
}
System.out.println();
}
Need to implement: support for comment lines, values for each element should be divided by maxvalue
, error checking for malformed files, exception handling. I tested it on a PGM file using UNIX end-of-lines, but it should work on Windows too.
Let me stress that this is not a robust nor complete implementation of a PGM parser. This code is intended just as proof of concept that maybe accomplishes just enough for your needs.
If you really need a robust PGM parser, you may use the tools provided by Netpbm.