mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 03:25:28 -04:00
#606: Workaround for broken JDK WBMPImageReader
(cherry picked from commit d0c4a075568304294b674de3f1d13a927e0084d0)
This commit is contained in:
parent
34852f7be5
commit
4d45ea4966
@ -125,27 +125,35 @@ public final class BufferedFileImageInputStream extends ImageInputStreamImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
|
public int read(final byte[] bytes, final int offset, final int length) throws IOException {
|
||||||
checkClosed();
|
checkClosed();
|
||||||
bitOffset = 0;
|
bitOffset = 0;
|
||||||
|
|
||||||
if (bufferEmpty()) {
|
if (bufferEmpty()) {
|
||||||
// Bypass buffer if buffer is empty for reads longer than buffer
|
// Bypass buffer if buffer is empty for reads longer than buffer
|
||||||
if (pLength >= buffer.length) {
|
if (length >= buffer.length) {
|
||||||
return readDirect(pBuffer, pOffset, pLength);
|
return readDirect(bytes, offset, length);
|
||||||
}
|
}
|
||||||
else if (!fillBuffer()) {
|
else if (!fillBuffer()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return readBuffered(pBuffer, pOffset, pLength);
|
int fromBuffer = readBuffered(bytes, offset, length);
|
||||||
|
|
||||||
|
if (length > fromBuffer) {
|
||||||
|
// Due to known bugs in certain JDK-bundled ImageIO plugins expecting read to behave as readFully,
|
||||||
|
// we'll read as much as possible from the buffer, and the rest directly after
|
||||||
|
return fromBuffer + max(0, readDirect(bytes, offset + fromBuffer, length - fromBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fromBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readDirect(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
|
private int readDirect(final byte[] bytes, final int offset, final int length) throws IOException {
|
||||||
// Invalidate the buffer, as its contents is no longer in sync with the stream's position.
|
// Invalidate the buffer, as its contents is no longer in sync with the stream's position.
|
||||||
bufferLimit = 0;
|
bufferLimit = 0;
|
||||||
int read = raf.read(pBuffer, pOffset, pLength);
|
int read = raf.read(bytes, offset, length);
|
||||||
|
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
streamPos += read;
|
streamPos += read;
|
||||||
@ -154,17 +162,17 @@ public final class BufferedFileImageInputStream extends ImageInputStreamImpl {
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readBuffered(final byte[] pBuffer, final int pOffset, final int pLength) {
|
private int readBuffered(final byte[] bytes, final int offset, final int length) {
|
||||||
// Read as much as possible from buffer
|
// Read as much as possible from buffer
|
||||||
int length = Math.min(bufferLimit - bufferPos, pLength);
|
int available = Math.min(bufferLimit - bufferPos, length);
|
||||||
|
|
||||||
if (length > 0) {
|
if (available > 0) {
|
||||||
System.arraycopy(buffer, bufferPos, pBuffer, pOffset, length);
|
System.arraycopy(buffer, bufferPos, bytes, offset, available);
|
||||||
bufferPos += length;
|
bufferPos += available;
|
||||||
streamPos += length;
|
streamPos += available;
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long length() {
|
public long length() {
|
||||||
|
@ -383,4 +383,23 @@ public class BufferedFileImageInputStreamTest {
|
|||||||
stream.close();
|
stream.close();
|
||||||
verify(mock, only()).close();
|
verify(mock, only()).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWorkaroundForWBMPImageReaderExpectsReadToBehaveAsReadFully() throws IOException {
|
||||||
|
// See #606 for details.
|
||||||
|
// Bug in JDK WBMPImageReader, uses read(byte[], int, int) instead of readFully(byte[], int, int).
|
||||||
|
// Ie: Relies on read to return all bytes at once, without blocking
|
||||||
|
int size = BufferedFileImageInputStream.DEFAULT_BUFFER_SIZE * 7;
|
||||||
|
byte[] bytes = new byte[size];
|
||||||
|
File file = randomDataToFile(bytes);
|
||||||
|
|
||||||
|
try (BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file)) {
|
||||||
|
byte[] result = new byte[size];
|
||||||
|
int head = stream.read(result, 0, 12); // Provoke a buffered read
|
||||||
|
int len = stream.read(result, 12, size - 12); // Rest of buffer + direct read
|
||||||
|
|
||||||
|
assertEquals(size, len + head);
|
||||||
|
assertArrayEquals(bytes, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user