// tokenizes a string for PBM and PGM headers and plain PBM and PGM data. If oneChar is true, // then // rather than parsing a whole string, a single character is read (not including whitespace or // comments) static String tokenizeString(InputStream stream, boolean oneChar) throws IOException { final int EOF = -1; StringBuilder b = new StringBuilder(); int c; boolean inComment = false; while (true) { c = stream.read(); if (c == EOF) throw new IOException( "Stream ended prematurely, before table reading was completed."); // no more tokens else if (inComment) { if (c == '\r' || c == '\n') // escape the comment inComment = false; else { } // do nothing } else if (Character.isWhitespace((char) c)) { } // do nothing else if (c == '#') // start of a comment { inComment = true; } else // start of a string { b.append((char) c); break; } } if (oneChar) return b.toString(); // at this point we have a valid string. We read until whitespace or a # while (true) { c = stream.read(); if (c == EOF) break; else if (c == '#') // start of comment, read until a '\n' { while (true) { c = stream.read(); // could hit EOF, which is fine if (c == EOF) break; else if (c == '\r' || c == '\n') break; } // break; // comments are not delimiters } else if (Character.isWhitespace((char) c)) break; else b.append((char) c); } return b.toString(); }
// Loads raw PGM files after the first-line header is stripped static int[][] loadRawPGM(InputStream stream) throws IOException { int width = tokenizeInt(stream); int height = tokenizeInt(stream); int maxVal = tokenizeInt(stream); if (width < 0) throw new IOException("Invalid width: " + width); if (height < 0) throw new IOException("Invalid height: " + height); if (maxVal <= 0) throw new IOException("Invalid maximum value: " + maxVal); // this single whitespace character will have likely already been consumed by reading maxVal // stream.read(); // must be a whitespace int[][] field = new int[width][height]; for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) { if (maxVal < 256) // one byte field[j][i] = stream.read(); else if (maxVal < 65536) // two bytes field[j][i] = (stream.read() << 8) & stream.read(); // two bytes, most significant byte first else if (maxVal < 16777216) // three bytes -- this is nonstandard field[j][i] = (stream.read() << 16) & (stream.read() << 8) & stream.read(); // three bytes, most significant byte first else // four bytes -- this is nonstandard field[j][i] = (stream.read() << 24) & (stream.read() << 16) & (stream.read() << 8) & stream.read(); // three bytes, most significant byte first } return field; }
// Loads raw PBM files after the first-line header is stripped static int[][] loadRawPBM(InputStream stream) throws IOException { int width = tokenizeInt(stream); int height = tokenizeInt(stream); if (width < 0) throw new IOException("Invalid width in PBM: " + width); if (height < 0) throw new IOException("Invalid height in PBM: " + height); // this single whitespace character will have likely already been consumed by reading height // stream.read(); // must be a whitespace int[][] field = new int[width][height]; for (int i = 0; i < height; i++) { int data = 0; int count = 0; for (int j = 0; j < width; j++) { if (count == 0) { data = stream.read(); count = 8; } count--; field[j][i] = (data >> count) & 0x1; } } return field; }