PNM: New attempt at making the new header parser work on Windows.

(cherry picked from commit 4b951c06cc)
This commit is contained in:
Harald Kuhr
2022-02-14 22:00:04 +01:00
parent 134eecc59f
commit 016977e382
4 changed files with 67 additions and 45 deletions
@@ -30,8 +30,10 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import javax.imageio.IIOException;
import com.twelvemonkeys.io.FastByteArrayOutputStream;
import javax.imageio.stream.ImageInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -70,45 +72,74 @@ final class PNMHeaderParser extends HeaderParser {
List<String> comments = new ArrayList<>();
StringBuilder tokenBuffer = new StringBuilder();
while (width == 0 || height == 0 || maxSample == 0) {
String line = input.readLine();
tokenBuffer.delete(0, tokenBuffer.length());
if (line == null) {
throw new IIOException("Unexpected end of stream");
}
while (tokenBuffer.length() < 16) { // Limit reads if we should read across into the binary part...
byte read = input.readByte();
int commentStart = line.indexOf('#');
if (commentStart >= 0) {
String comment = line.substring(commentStart + 1).trim();
if (!comment.isEmpty()) {
comments.add(comment);
if (read == '#') {
// Read rest of the line as comment
String comment = readLineUTF8(input).trim();
if (!comment.isEmpty()) {
comments.add(comment);
}
break;
}
else if (Character.isWhitespace((char) read)) {
if (tokenBuffer.length() > 0) {
break;
}
}
else {
tokenBuffer.append((char) read);
}
line = line.substring(0, commentStart);
}
line = line.trim();
String token = tokenBuffer.toString().trim();
if (!line.isEmpty()) {
if (!token.isEmpty()) {
// We have tokens...
String[] tokens = line.split("\\s");
for (String token : tokens) {
if (width == 0) {
width = Integer.parseInt(token);
}
else if (height == 0) {
height = Integer.parseInt(token);
}
else if (maxSample == 0) {
maxSample = Integer.parseInt(token);
}
else {
throw new IIOException("Unknown PNM token: " + token);
}
if (width == 0) {
width = Integer.parseInt(token);
}
else if (height == 0) {
height = Integer.parseInt(token);
}
else {
maxSample = Integer.parseInt(token);
}
}
}
return new PNMHeader(fileType, tupleType, width, height, tupleType.getSamplesPerPixel(), maxSample, comments);
}
// Similar to DataInput.readLine, except it uses UTF8 encoding
private static String readLineUTF8(final ImageInputStream input) throws IOException {
ByteArrayOutputStream buffer = new FastByteArrayOutputStream(128);
int value;
do {
switch (value = input.read()) {
case '\r':
// Check for CR + LF pattern and skip, otherwise fall through
if (input.read() != '\n') {
input.seek(input.getStreamPosition() - 1);
}
case '\n':
case -1:
value = -1;
break;
default:
buffer.write(value);
}
} while (value != -1);
return buffer.toString("UTF8");
}
}
@@ -58,17 +58,13 @@ final class Plain16BitDecoder extends InputStream {
}
// Each number is one byte. Skip whitespace.
if (currentLine == null || !currentLine.hasNext()) {
while (currentLine == null || !currentLine.hasNext()) {
String line = reader.readLine();
if (line == null) {
return -1;
}
currentLine = new StringTokenIterator(line);
if (!currentLine.hasNext()) {
return -1;
}
}
int next = Integer.parseInt(currentLine.next()) & 0xffff;
@@ -50,17 +50,13 @@ final class Plain8BitDecoder extends InputStream {
@Override
public int read() throws IOException {
// Each number is one byte. Skip whitespace.
if (currentLine == null || !currentLine.hasNext()) {
while (currentLine == null || !currentLine.hasNext()) {
String line = reader.readLine();
if (line == null) {
return -1;
}
currentLine = new StringTokenIterator(line);
if (!currentLine.hasNext()) {
return -1;
}
}
return Integer.parseInt(currentLine.next()) & 0xff;