#738 PSD: No longer decompress PackBits across boundaries

(cherry picked from commit 606fd53823623ba866fc4e31ce7fa751278fd51d)
This commit is contained in:
Harald Kuhr 2023-03-18 10:33:34 +01:00
parent bf55209bf6
commit 4a51850e9b
2 changed files with 35 additions and 34 deletions

View File

@ -41,21 +41,20 @@ import java.io.InputStream;
* underlying stream. * underlying stream.
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/SubStream.java#2 $
*/ */
public final class SubStream extends FilterInputStream { public final class SubStream extends FilterInputStream {
private long bytesLeft; private long bytesLeft;
private int markLimit; private int markLimit;
/** /**
* Creates a {@code SubStream} of the given {@code pStream}. * Creates a {@code SubStream} of the given {@code stream}.
* *
* @param pStream the underlying input stream * @param stream the underlying input stream
* @param pLength maximum number of bytes to read drom this stream * @param length maximum number of bytes to read from this stream
*/ */
public SubStream(final InputStream pStream, final long pLength) { public SubStream(final InputStream stream, final long length) {
super(Validate.notNull(pStream, "stream")); super(Validate.notNull(stream, "stream"));
bytesLeft = pLength; bytesLeft = length;
} }
/** /**
@ -73,13 +72,13 @@ public final class SubStream extends FilterInputStream {
@Override @Override
public int available() throws IOException { public int available() throws IOException {
return (int) Math.min(super.available(), bytesLeft); return (int) findMaxLen(super.available());
} }
@Override @Override
public void mark(int pReadLimit) { public void mark(int readLimit) {
super.mark(pReadLimit);// This either succeeds or does nothing... super.mark(readLimit);// This either succeeds or does nothing...
markLimit = pReadLimit; markLimit = readLimit;
} }
@Override @Override
@ -93,44 +92,42 @@ public final class SubStream extends FilterInputStream {
if (bytesLeft-- <= 0) { if (bytesLeft-- <= 0) {
return -1; return -1;
} }
return super.read(); return super.read();
} }
@Override @Override
public final int read(byte[] pBytes) throws IOException { public int read(byte[] bytes) throws IOException {
return read(pBytes, 0, pBytes.length); return read(bytes, 0, bytes.length);
} }
@Override @Override
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException { public int read(final byte[] bytes, final int off, final int len) throws IOException {
if (bytesLeft <= 0) { if (bytesLeft <= 0) {
return -1; return -1;
} }
int read = super.read(pBytes, pOffset, (int) findMaxLen(pLength)); int read = super.read(bytes, off, (int) findMaxLen(len));
bytesLeft = read < 0 ? 0 : bytesLeft - read; bytesLeft = read < 0 ? 0 : bytesLeft - read;
return read; return read;
} }
@Override
public long skip(long length) throws IOException {
long skipped = super.skip(findMaxLen(length));// Skips 0 or more, never -1
bytesLeft -= skipped;
return skipped;
}
/** /**
* Finds the maximum number of bytes we can read or skip, from this stream. * Finds the maximum number of bytes we can read or skip, from this stream.
* *
* @param pLength the requested length * @param length the requested length
* @return the maximum number of bytes to read * @return the maximum number of bytes to read
*/ */
private long findMaxLen(long pLength) { private long findMaxLen(long length) {
if (bytesLeft < pLength) { return bytesLeft < length ? Math.max(bytesLeft, 0) : length;
return (int) Math.max(bytesLeft, 0);
}
else {
return pLength;
}
}
@Override
public long skip(long pLength) throws IOException {
long skipped = super.skip(findMaxLen(pLength));// Skips 0 or more, never -1
bytesLeft -= skipped;
return skipped;
} }
} }

View File

@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.psd;
import com.twelvemonkeys.imageio.stream.DirectImageInputStream; import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
import com.twelvemonkeys.imageio.stream.SubImageInputStream; import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.io.SubStream;
import com.twelvemonkeys.io.enc.DecoderStream; import com.twelvemonkeys.io.enc.DecoderStream;
import com.twelvemonkeys.io.enc.PackBitsDecoder; import com.twelvemonkeys.io.enc.PackBitsDecoder;
import com.twelvemonkeys.lang.StringUtil; import com.twelvemonkeys.lang.StringUtil;
@ -107,7 +108,8 @@ final class PSDUtil {
return new SubImageInputStream(stream, streamLength < 0 ? Long.MAX_VALUE : streamLength); return new SubImageInputStream(stream, streamLength < 0 ? Long.MAX_VALUE : streamLength);
case PSD.COMPRESSION_RLE: case PSD.COMPRESSION_RLE:
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(byteCounts, stream))); int rowLength = (columns * bitsPerSample + 7) / 8;
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(stream, byteCounts, rowLength)));
case PSD.COMPRESSION_ZIP: case PSD.COMPRESSION_ZIP:
return new DirectImageInputStream(new InflaterInputStream(createStreamAdapter(stream, compressedLength))); return new DirectImageInputStream(new InflaterInputStream(createStreamAdapter(stream, compressedLength)));
@ -124,11 +126,13 @@ final class PSDUtil {
private static class LazyPackBitsStreamEnumeration implements Enumeration<InputStream> { private static class LazyPackBitsStreamEnumeration implements Enumeration<InputStream> {
private final ImageInputStream stream; private final ImageInputStream stream;
private final int[] byteCounts; private final int[] byteCounts;
private final int rowLength;
private int index; private int index;
public LazyPackBitsStreamEnumeration(int[] byteCounts, ImageInputStream stream) { public LazyPackBitsStreamEnumeration(ImageInputStream stream, int[] byteCounts, int rowLength) {
this.byteCounts = byteCounts;
this.stream = stream; this.stream = stream;
this.byteCounts = byteCounts;
this.rowLength = rowLength;
} }
@Override @Override
@ -138,7 +142,7 @@ final class PSDUtil {
@Override @Override
public InputStream nextElement() { public InputStream nextElement() {
return new DecoderStream(createStreamAdapter(stream, byteCounts[index++]), new PackBitsDecoder()); return new SubStream(new DecoderStream(createStreamAdapter(stream, byteCounts[index++]), new PackBitsDecoder(), rowLength), rowLength);
} }
} }
} }