- Moved unused encoders/decoders to sandbox

- Fixed Base64 encoder/decoder to pass test cases
- Minor clean-up in other decoders
This commit is contained in:
Harald Kuhr 2009-09-18 22:46:31 +02:00
parent 40a5960a9f
commit c45882846a
20 changed files with 259 additions and 139 deletions

View File

@ -33,7 +33,7 @@ import java.io.IOException;
import java.io.InputStream;
/**
* Abstract base class for RLE decoding as specifed by in the Windows BMP (aka DIB) file format.
* Abstract base class for RLE decoding as specified by in the Windows BMP (aka DIB) file format.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@ -59,9 +59,11 @@ abstract class AbstractRLEDecoder implements Decoder {
mWidth = pWidth;
int bytesPerRow = mWidth;
int mod = bytesPerRow % 4;
if (mod != 0) {
bytesPerRow += 4 - mod;
}
mRow = new byte[bytesPerRow];
mSrcX = 0;
@ -133,6 +135,7 @@ abstract class AbstractRLEDecoder implements Decoder {
if (pByte < 0) {
throw new EOFException("Premature end of file");
}
return pByte;
}
}

View File

@ -43,7 +43,7 @@ import java.io.*;
* @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/enc/Base64Decoder.java#2 $
*/
public class Base64Decoder implements Decoder {
public final class Base64Decoder implements Decoder {
/**
* This array maps the characters to their 6 bit values
*/
@ -60,12 +60,14 @@ public class Base64Decoder implements Decoder {
};
final static byte[] PEM_CONVERT_ARRAY;
private byte[] decode_buffer = new byte[4];
private byte[] mDecodeBuffer = new byte[4];
private ByteArrayOutputStream mWrapped;
private Object mWrappedObject;
static {
PEM_CONVERT_ARRAY = new byte[256];
for (int i = 0; i < 255; i++) {
PEM_CONVERT_ARRAY[i] = -1;
}
@ -75,20 +77,23 @@ public class Base64Decoder implements Decoder {
}
}
protected static int readFully(InputStream pStream, byte pBytes[],
int pOffset, int pLength) throws IOException {
protected static int readFully(final InputStream pStream, final byte pBytes[], final int pOffset, final int pLength)
throws IOException
{
for (int i = 0; i < pLength; i++) {
int read = pStream.read();
if (read == -1) {
return i != 0 ? i : -1;
}
pBytes[i + pOffset] = (byte) read;
}
return pLength;
}
protected boolean decodeAtom(InputStream pInput, OutputStream pOutput, int pLength)
protected boolean decodeAtom(final InputStream pInput, final OutputStream pOutput, final int pLength)
throws IOException {
byte byte0 = -1;
@ -102,40 +107,45 @@ public class Base64Decoder implements Decoder {
int read;
// Skip linefeeds
// Skip line feeds
do {
read = pInput.read();
if (read == -1) {
return false;
}
} while (read == 10 || read == 13);
decode_buffer[0] = (byte) read;
read = readFully(pInput, decode_buffer, 1, pLength - 1);
mDecodeBuffer[0] = (byte) read;
read = readFully(pInput, mDecodeBuffer, 1, pLength - 1);
if (read == -1) {
return false;
}
if (pLength > 3 && decode_buffer[3] == 61) {
pLength = 3;
}
if (pLength > 2 && decode_buffer[2] == 61) {
pLength = 2;
int length = pLength;
if (length > 3 && mDecodeBuffer[3] == 61) {
length = 3;
}
switch (pLength) {
if (length > 2 && mDecodeBuffer[2] == 61) {
length = 2;
}
switch (length) {
case 4:
byte3 = PEM_CONVERT_ARRAY[decode_buffer[3] & 255];
byte3 = PEM_CONVERT_ARRAY[mDecodeBuffer[3] & 255];
// fall through
case 3:
byte2 = PEM_CONVERT_ARRAY[decode_buffer[2] & 255];
byte2 = PEM_CONVERT_ARRAY[mDecodeBuffer[2] & 255];
// fall through
case 2:
byte1 = PEM_CONVERT_ARRAY[decode_buffer[1] & 255];
byte0 = PEM_CONVERT_ARRAY[decode_buffer[0] & 255];
byte1 = PEM_CONVERT_ARRAY[mDecodeBuffer[1] & 255];
byte0 = PEM_CONVERT_ARRAY[mDecodeBuffer[0] & 255];
// fall through
default:
switch (pLength) {
switch (length) {
case 2:
pOutput.write((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
break;
@ -149,16 +159,18 @@ public class Base64Decoder implements Decoder {
pOutput.write((byte) (byte2 << 6 & 192 | byte3 & 63));
break;
}
break;
}
return true;
}
void decodeBuffer(InputStream pInput, ByteArrayOutputStream pOutput, int pLength) throws IOException {
void decodeBuffer(final InputStream pInput, final ByteArrayOutputStream pOutput, final int pLength) throws IOException {
do {
int k = 72;
int i;
for (i = 0; i + 4 < k; i += 4) {
if(!decodeAtom(pInput, pOutput, 4)) {
break;
@ -169,17 +181,17 @@ public class Base64Decoder implements Decoder {
break;
}
}
while (true);
while (pOutput.size() + 54 < pLength); // 72 char lines should produce no more than 54 bytes
}
public int decode(InputStream pStream, byte[] pBuffer) throws IOException {
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
if (mWrappedObject != pBuffer) {
// NOTE: Array not cloned in FastByteArrayOutputStream
mWrapped = new FastByteArrayOutputStream(pBuffer);
mWrappedObject = pBuffer;
}
mWrapped.reset(); // NOTE: This only resets count to 0
mWrapped.reset(); // NOTE: This only resets count to 0
decodeBuffer(pStream, mWrapped, pBuffer.length);
return mWrapped.size();

View File

@ -44,26 +44,37 @@ import java.io.IOException;
*/
public class Base64Encoder implements Encoder {
public void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
public void encode(final OutputStream pStream, final byte[] pBuffer, final int pOffset, final int pLength)
throws IOException
{
if (pOffset < 0 || pOffset > pLength || pOffset > pBuffer.length) {
throw new IndexOutOfBoundsException("offset outside [0...length]");
}
else if (pLength > pBuffer.length) {
throw new IndexOutOfBoundsException("length > buffer length");
}
// TODO: Implement
// NOTE: This is impossible, given the current spec, as we need to either:
// - buffer all data in the EncoderStream
// - or have flush/end method(s) in the Encoder
// to ensure proper end of stream handling
int length = pLength;
int offset = pOffset;
// TODO: Temp impl, will only work for single writes
while ((pBuffer.length - offset) > 0) {
byte a, b, c;
if ((pBuffer.length - offset) > 2) {
pLength = 3;
length = 3;
}
else {
pLength = pBuffer.length - offset;
length = pBuffer.length - offset;
}
switch (pLength) {
switch (length) {
case 1:
a = pBuffer[offset];
b = 0;

View File

@ -33,7 +33,7 @@ import java.io.IOException;
import java.io.FilterInputStream;
/**
* An {@code InputStream} that provides on-the-fly deoding from an underlying
* An {@code InputStream} that provides on-the-fly decoding from an underlying
* stream.
* <p/>
* @see EncoderStream
@ -54,11 +54,11 @@ public final class DecoderStream extends FilterInputStream {
* input stream specified by the {@code pStream} argument.
*
* @param pStream the underlying input stream.
* @param pDecoder
* @param pDecoder the decoder that will be used to decode the underlying stream
*
* @see java.io.FilterInputStream#in
*/
public DecoderStream(InputStream pStream, Decoder pDecoder) {
public DecoderStream(final InputStream pStream, final Decoder pDecoder) {
super(pStream);
mDecoder = pDecoder;
mBuffer = new byte[1024];
@ -92,7 +92,7 @@ public final class DecoderStream extends FilterInputStream {
}
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
throw new IndexOutOfBoundsException("bytes.length=" + pBytes.length + " offset=" + pOffset + " lenght=" + pLength);
throw new IndexOutOfBoundsException("bytes.length=" + pBytes.length + " offset=" + pOffset + " length=" + pLength);
}
else if (pLength == 0) {
return 0;
@ -106,6 +106,7 @@ public final class DecoderStream extends FilterInputStream {
// Read until we have read pLength bytes, or have reached EOF
int count = 0;
int off = pOffset;
while (pLength > count) {
int avail = mBufferLimit - mBufferPos;
@ -120,6 +121,7 @@ public final class DecoderStream extends FilterInputStream {
// Copy as many bytes as possible
int dstLen = Math.min(pLength - count, avail);
System.arraycopy(mBuffer, mBufferPos, pBytes, off, dstLen);
mBufferPos += dstLen;
// Update offset (rest)
@ -129,13 +131,6 @@ public final class DecoderStream extends FilterInputStream {
count += dstLen;
}
/*
for (int i = 0; i < count; i++) {
byte b = pBytes[pOffset + i];
System.out.print("0x" + Integer.toHexString(b & 0xff));
}
*/
return count;
}
@ -179,11 +174,18 @@ public final class DecoderStream extends FilterInputStream {
*/
protected int fill() throws IOException {
int read = mDecoder.decode(in, mBuffer);
// TODO: Enforce this in test case, leave here to aid debugging
if (read > mBuffer.length) {
throw new AssertionError(String.format("Decode beyond buffer (%d): %d", mBuffer.length, read));
}
mBufferPos = 0;
if (read == 0) {
return -1;
}
return read;
}
}

View File

@ -47,7 +47,7 @@ import java.io.OutputStream;
public interface Encoder {
/**
* Encodes up to {@code pBuffer.length} bytes into the given inputstream,
* Encodes up to {@code pBuffer.length} bytes into the given input stream,
* from the given buffer.
*
* @param pStream the outputstream to encode data to

View File

@ -55,9 +55,9 @@ public final class EncoderStream extends FilterOutputStream {
* underlying output stream.
*
* @param pStream the underlying output stream
* @param pEncoder
* @param pEncoder the encoder to use
*/
public EncoderStream(OutputStream pStream, Encoder pEncoder) {
public EncoderStream(final OutputStream pStream, final Encoder pEncoder) {
this(pStream, pEncoder, false);
}
@ -66,11 +66,11 @@ public final class EncoderStream extends FilterOutputStream {
* underlying output stream.
*
* @param pStream the underlying output stream
* @param pEncoder
* @param pEncoder the encoder to use
* @param pFlushOnWrite if {@code true}, calls to the byte-array
* {@code write} methods will automatically flush the buffer.
*/
public EncoderStream(OutputStream pStream, Encoder pEncoder, boolean pFlushOnWrite) {
public EncoderStream(final OutputStream pStream, final Encoder pEncoder, final boolean pFlushOnWrite) {
super(pStream);
mEncoder = pEncoder;
@ -94,12 +94,13 @@ public final class EncoderStream extends FilterOutputStream {
if (mBufferPos != 0) {
// Make sure all remaining data in buffer is written to the stream
mEncoder.encode(out, mBuffer, 0, mBufferPos);
// Reset buffer
mBufferPos = 0;
}
}
public final void write(byte[] pBytes) throws IOException {
public final void write(final byte[] pBytes) throws IOException {
write(pBytes, 0, pBytes.length);
}
@ -107,14 +108,14 @@ public final class EncoderStream extends FilterOutputStream {
// TODO: We might need a way to explicitly flush the encoder, or specify
// that the encoder can't buffer. In that case, the encoder should probably
// tell the EncoderStream how large buffer it prefers...
public void write(byte[] pBytes, int pOffset, int pLength) throws IOException {
public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (!mFlushOnWrite && mBufferPos + pLength < mBuffer.length) {
// Buffer data
System.arraycopy(pBytes, pOffset, mBuffer, mBufferPos, pLength);
mBufferPos += pLength;
}
else {
// Encode data allready in the buffer
// Encode data already in the buffer
if (mBufferPos != 0) {
encodeBuffer();
}
@ -124,10 +125,11 @@ public final class EncoderStream extends FilterOutputStream {
}
}
public void write(int pByte) throws IOException {
public void write(final int pByte) throws IOException {
if (mBufferPos >= mBuffer.length - 1) {
encodeBuffer(); // Resets mBufferPos to 0
}
mBuffer[mBufferPos++] = (byte) pByte;
}
}

View File

@ -62,31 +62,31 @@ public final class PackBits16Decoder implements Decoder {
/**
* Creates a {@code PackBitsDecoder}.
* <p/>
* As some implementations of PackBits-like encoders treat -128 as lenght of
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops
* for compatibility.
* Should be used with caution, even though, most known encoders never write
* no-ops in the compressed streams.
*
* @param pDisableNoop
* @param pDisableNoop {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBits16Decoder(boolean pDisableNoop) {
public PackBits16Decoder(final boolean pDisableNoop) {
mDisableNoop = pDisableNoop;
}
/**
* Decodes bytes from the given input stream, to the given buffer.
*
* @param pStream
* @param pStream the stream to decode from
* @param pBuffer a byte array, minimum 128 (or 129 if no-op is disabled)
* bytes long
* @return The number of bytes decoded
*
* @throws java.io.IOException
*/
public int decode(InputStream pStream, byte[] pBuffer) throws IOException {
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
if (mEOF) {
throw new EOFException("Unexpected end of PackBits stream");
return -1;
}
int read = 0;
@ -94,6 +94,7 @@ public final class PackBits16Decoder implements Decoder {
while (read < max) {
int n;
if (mSplitRun) {
// Continue run
n = mLeftOfRun;
@ -149,24 +150,30 @@ public final class PackBits16Decoder implements Decoder {
return read;
}
private static byte readByte(InputStream pStream) throws IOException {
private static byte readByte(final InputStream pStream) throws IOException {
int read = pStream.read();
if (read < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
return (byte) read;
}
private static void readFully(InputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
private static void readFully(final InputStream pStream, final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
if (pLength < 0) {
throw new IndexOutOfBoundsException();
}
int read = 0;
while (read < pLength) {
int count = pStream.read(pBuffer, pOffset + read, pLength - read);
if (count < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
read += count;
}
}

View File

@ -69,9 +69,7 @@ public final class PackBitsDecoder implements Decoder {
private boolean mSplitRun;
private boolean mEOF;
/**
* Creates a {@code PackBitsDecoder}.
*/
/** Creates a {@code PackBitsDecoder}. */
public PackBitsDecoder() {
this(false);
}
@ -79,31 +77,31 @@ public final class PackBitsDecoder implements Decoder {
/**
* Creates a {@code PackBitsDecoder}.
* <p/>
* As some implementations of PackBits-like encoders treat -128 as lenght of
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops
* for compatibility.
* Should be used with caution, even though, most known encoders never write
* no-ops in the compressed streams.
*
* @param pDisableNoop
* @param pDisableNoop {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBitsDecoder(boolean pDisableNoop) {
public PackBitsDecoder(final boolean pDisableNoop) {
mDisableNoop = pDisableNoop;
}
/**
* Decodes bytes from the given input stream, to the given buffer.
*
* @param pStream
* @param pStream the stream to decode from
* @param pBuffer a byte array, minimum 128 (or 129 if no-op is disabled)
* bytes long
* @return The number of bytes decoded
*
* @throws IOException
*/
public int decode(InputStream pStream, byte[] pBuffer) throws IOException {
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
if (mEOF) {
throw new EOFException("Unexpected end of PackBits stream");
return -1;
}
int read = 0;
@ -111,6 +109,7 @@ public final class PackBitsDecoder implements Decoder {
while (read < max) {
int n;
if (mSplitRun) {
// Continue run
n = mLeftOfRun;
@ -164,24 +163,30 @@ public final class PackBitsDecoder implements Decoder {
return read;
}
private static byte readByte(InputStream pStream) throws IOException {
private static byte readByte(final InputStream pStream) throws IOException {
int read = pStream.read();
if (read < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
return (byte) read;
}
private static void readFully(InputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
private static void readFully(final InputStream pStream, final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
if (pLength < 0) {
throw new IndexOutOfBoundsException();
}
int read = 0;
while (read < pLength) {
int count = pStream.read(pBuffer, pOffset + read, pLength - read);
if (count < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
read += count;
}
}

View File

@ -52,6 +52,7 @@ final class RLE4Decoder extends AbstractRLEDecoder {
while (mSrcY >= 0) {
int byte1 = pInput.read();
int byte2 = checkEOF(pInput.read());
if (byte1 == 0x00) {
switch (byte2) {
case 0x00:
@ -102,6 +103,7 @@ final class RLE4Decoder extends AbstractRLEDecoder {
mRow[mSrcX++] = (byte) byte2;
byte1 -= 2;
}
if (byte1 == 1) {
// TODO: Half byte alignment? Seems to be ok...
mRow[mSrcX++] = (byte) (byte2 & 0xf0);
@ -110,14 +112,15 @@ final class RLE4Decoder extends AbstractRLEDecoder {
// If we're done with a complete row, copy the data
if (mSrcX == mRow.length) {
// Move to new position, either absolute (delta) or next line
if (deltaX != 0 || deltaY != 0) {
mSrcX = (deltaX + 1) / 2;
if (deltaY > mSrcY) {
mSrcY = deltaY;
break;
}
deltaX = 0;
deltaY = 0;
}

View File

@ -52,6 +52,7 @@ final class RLE8Decoder extends AbstractRLEDecoder {
while (mSrcY >= 0) {
int byte1 = pInput.read();
int byte2 = checkEOF(pInput.read());
if (byte1 == 0x00) {
switch (byte2) {
case 0x00:

View File

@ -20,14 +20,14 @@ public class Base64EncoderTestCase extends EncoderAbstractTestCase {
}
public void testNegativeEncode() throws IOException {
Encoder base64 = createEncoder();
Encoder encoder = createEncoder();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try {
base64.encode(bytes, new byte[1], 2, 1);
encoder.encode(bytes, new byte[1], 2, 1);
fail("wrong index should throw IndexOutOfBoundsException");
}
catch (IndexOutOfBoundsException e) {
catch (IndexOutOfBoundsException expected) {
}
}

View File

@ -1,11 +1,7 @@
package com.twelvemonkeys.io.enc;
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
import com.twelvemonkeys.io.enc.Decoder;
import com.twelvemonkeys.io.enc.DecoderStream;
import com.twelvemonkeys.io.enc.Encoder;
import com.twelvemonkeys.io.enc.EncoderStream;
import com.twelvemonkeys.io.FileUtil;
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
import java.io.*;
import java.util.Arrays;
@ -86,14 +82,34 @@ public abstract class DecoderAbstractTestCase extends ObjectAbstractTestCase {
}
public final void testStreams() throws Exception {
for (int i = 0; i < 100; ++i) {
runStreamTest(i);
for (int i = 0; i < 100; i++) {
try {
runStreamTest(i);
}
catch (IOException e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
for (int i = 100; i < 2000; i += 250) {
runStreamTest(i);
try {
runStreamTest(i);
}
catch (IOException e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
for (int i = 2000; i < 80000; i += 1000) {
runStreamTest(i);
try {
runStreamTest(i);
}
catch (IOException e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
}
}

View File

@ -1,11 +1,7 @@
package com.twelvemonkeys.io.enc;
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
import com.twelvemonkeys.io.enc.Decoder;
import com.twelvemonkeys.io.enc.DecoderStream;
import com.twelvemonkeys.io.enc.Encoder;
import com.twelvemonkeys.io.enc.EncoderStream;
import com.twelvemonkeys.io.FileUtil;
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
import java.io.*;
import java.util.Arrays;
@ -31,58 +27,99 @@ public abstract class EncoderAbstractTestCase extends ObjectAbstractTestCase {
}
public final void testNullEncode() throws IOException {
Encoder base64 = createEncoder();
Encoder encoder = createEncoder();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try {
base64.encode(bytes, null, 0, 1);
encoder.encode(bytes, null, 0, 1);
fail("null should throw NullPointerException");
}
catch (NullPointerException e) {
catch (NullPointerException expected) {
}
}
private byte[] createData(int pLength) throws Exception {
private byte[] createData(final int pLength) throws Exception {
byte[] bytes = new byte[pLength];
RANDOM.nextBytes(bytes);
return bytes;
}
private void runStreamTest(int pLength) throws Exception {
private void runStreamTest(final int pLength) throws Exception {
byte[] data = createData(pLength);
ByteArrayOutputStream out_bytes = new ByteArrayOutputStream();
OutputStream out = new EncoderStream(out_bytes, createEncoder(), true);
out.write(data);
out.close();
byte[] encoded = out_bytes.toByteArray();
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
OutputStream out = new EncoderStream(outBytes, createEncoder(), true);
try {
out.write(data);
}
finally {
out.close();
}
byte[] encoded = outBytes.toByteArray();
// System.err.println("encoded.length: " + encoded.length);
// System.err.println("encoded: " + Arrays.toString(encoded));
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createCompatibleDecoder()));
assertTrue(Arrays.equals(data, decoded));
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createCompatibleDecoder());
out_bytes = new ByteArrayOutputStream();
/**
byte[] buffer = new byte[3];
for (int n = in.read(buffer); n > 0; n = in.read(buffer)) {
out_bytes.write(buffer, 0, n);
}
//*/
FileUtil.copy(in, out_bytes);
outBytes = new ByteArrayOutputStream();
out_bytes.close();
in.close();
decoded = out_bytes.toByteArray();
try {
FileUtil.copy(in, outBytes);
}
finally {
outBytes.close();
in.close();
}
decoded = outBytes.toByteArray();
assertTrue(Arrays.equals(data, decoded));
}
public final void testStreams() throws Exception {
for (int i = 0; i < 100; ++i) {
runStreamTest(i);
for (int i = 0; i < 100; i++) {
try {
runStreamTest(i);
}
catch (IOException e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
catch (Exception e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
for (int i = 100; i < 2000; i += 250) {
runStreamTest(i);
try {
runStreamTest(i);
}
catch (IOException e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
catch (Exception e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
for (int i = 2000; i < 80000; i += 1000) {
runStreamTest(i);
try {
runStreamTest(i);
}
catch (IOException e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
catch (Exception e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
}
}

View File

@ -30,12 +30,12 @@ package com.twelvemonkeys.imageio.plugins.psd;
import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.io.enc.DecoderStream;
import com.twelvemonkeys.io.enc.InflateDecoder;
import com.twelvemonkeys.io.enc.PackBitsDecoder;
import javax.imageio.stream.ImageInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.zip.ZipInputStream;
/**
* PSDUtil
@ -81,7 +81,8 @@ final class PSDUtil {
}
static DataInputStream createZipStream(final ImageInputStream pInput, int pLength) {
return new DataInputStream(new DecoderStream(IIOUtil.createStreamAdapter(pInput, pLength), new InflateDecoder()));
//return new DataInputStream(new DecoderStream(IIOUtil.createStreamAdapter(pInput, pLength), new InflateDecoder()));
return new DataInputStream(new ZipInputStream(IIOUtil.createStreamAdapter(pInput, pLength)));
}
static DataInputStream createZipPredictorStream(final ImageInputStream pInput, int pLength) {

View File

@ -36,31 +36,55 @@ import java.util.zip.Deflater;
* {@code Encoder} implementation for standard DEFLATE encoding.
* <p/>
*
* @see <a href="http://tools.ietf.org/html/rfc1951">RFC 1951</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/enc/DeflateEncoder.java#2 $
*
* @see <a href="http://tools.ietf.org/html/rfc1951">RFC 1951</a>
* @see Deflater
* @see InflateDecoder
* @see java.util.zip.DeflaterOutputStream
*
* @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/enc/DeflateEncoder.java#2 $
*/
public final class DeflateEncoder implements Encoder {
final class DeflateEncoder implements Encoder {
private final Deflater mDeflater;
private final byte[] mBuffer = new byte[1024];
public DeflateEncoder() {
this(new Deflater());
// this(new Deflater());
this(new Deflater(Deflater.DEFAULT_COMPRESSION, true)); // TODO: Should we use "no wrap"?
}
public DeflateEncoder(Deflater pDeflater) {
public DeflateEncoder(final Deflater pDeflater) {
if (pDeflater == null) {
throw new IllegalArgumentException("deflater == null");
}
mDeflater = pDeflater;
}
public void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
throw new InternalError("not implemented: encode()"); // TODO: Implement
public void encode(final OutputStream pStream, final byte[] pBuffer, final int pOffset, final int pLength)
throws IOException
{
System.out.println("DeflateEncoder.encode");
mDeflater.setInput(pBuffer, pOffset, pLength);
flushInputToStream(pStream);
}
private void flushInputToStream(final OutputStream pStream) throws IOException {
System.out.println("DeflateEncoder.flushInputToStream");
if (mDeflater.needsInput()) {
System.out.println("Foo");
}
while (!mDeflater.needsInput()) {
int deflated = mDeflater.deflate(mBuffer, 0, mBuffer.length);
pStream.write(mBuffer, 0, deflated);
System.out.println("flushed " + deflated);
}
}
// public void flush() {
// mDeflater.finish();
// }
}

View File

@ -47,7 +47,7 @@ import java.util.zip.Inflater;
* @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/enc/InflateDecoder.java#2 $
*/
public final class InflateDecoder implements Decoder {
final class InflateDecoder implements Decoder {
private final Inflater mInflater;
@ -66,25 +66,29 @@ public final class InflateDecoder implements Decoder {
*
* @param pInflater the inflater instance to use
*/
public InflateDecoder(Inflater pInflater) {
public InflateDecoder(final Inflater pInflater) {
if (pInflater == null) {
throw new IllegalArgumentException("inflater == null");
}
mInflater = pInflater;
mBuffer = new byte[1024];
}
public int decode(InputStream pStream, byte[] pBuffer) throws IOException {
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
try {
int decoded;
while ((decoded = mInflater.inflate(pBuffer, 0, pBuffer.length)) == 0) {
if (mInflater.finished() || mInflater.needsDictionary()) {
return 0;
}
if (mInflater.needsInput()) {
fill(pStream);
}
}
return decoded;
}
catch (DataFormatException e) {
@ -93,11 +97,13 @@ public final class InflateDecoder implements Decoder {
}
}
private void fill(InputStream pStream) throws IOException {
private void fill(final InputStream pStream) throws IOException {
int available = pStream.read(mBuffer, 0, mBuffer.length);
if (available == -1) {
throw new EOFException("Unexpected end of ZLIB stream");
}
mInflater.setInput(mBuffer, 0, available);
}
}

View File

@ -38,7 +38,7 @@ import java.io.IOException;
* @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/enc/LZWDecoder.java#2 $
*/
public class LZWDecoder implements Decoder {
final class LZWDecoder implements Decoder {
public int decode(InputStream pStream, byte[] pBuffer) throws IOException {
return 0; // TODO: Implement
// TODO: We probably need a GIF specific subclass

View File

@ -38,7 +38,7 @@ import java.io.IOException;
* @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/enc/LZWEncoder.java#2 $
*/
public class LZWEncoder implements Encoder {
final class LZWEncoder implements Encoder {
public void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
// TODO: Implement
// TODO: We probably need a GIF specific subclass

View File

@ -1,18 +1,13 @@
package com.twelvemonkeys.io.enc;
import com.twelvemonkeys.io.enc.Decoder;
import com.twelvemonkeys.io.enc.DeflateEncoder;
import com.twelvemonkeys.io.enc.Encoder;
import com.twelvemonkeys.io.enc.InflateDecoder;
/**
* DeflateDecoderTest
* DeflateEncoderTest
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/enc/DeflateDecoderTestCase.java#1 $
*/
public class DeflateDecoderTestCase extends EncoderAbstractTestCase {
public class DeflateEncoderTestCase extends EncoderAbstractTestCase {
protected Encoder createEncoder() {
return new DeflateEncoder();
}

View File

@ -1,10 +1,5 @@
package com.twelvemonkeys.io.enc;
import com.twelvemonkeys.io.enc.Decoder;
import com.twelvemonkeys.io.enc.DeflateEncoder;
import com.twelvemonkeys.io.enc.Encoder;
import com.twelvemonkeys.io.enc.InflateDecoder;
/**
* InflateEncoderTest
* <p/>