mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 03:25:28 -04:00
- 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:
parent
40a5960a9f
commit
c45882846a
5
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/AbstractRLEDecoder.java
Executable file → Normal file
5
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/AbstractRLEDecoder.java
Executable file → Normal file
@ -33,7 +33,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
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/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
@ -59,9 +59,11 @@ abstract class AbstractRLEDecoder implements Decoder {
|
|||||||
mWidth = pWidth;
|
mWidth = pWidth;
|
||||||
int bytesPerRow = mWidth;
|
int bytesPerRow = mWidth;
|
||||||
int mod = bytesPerRow % 4;
|
int mod = bytesPerRow % 4;
|
||||||
|
|
||||||
if (mod != 0) {
|
if (mod != 0) {
|
||||||
bytesPerRow += 4 - mod;
|
bytesPerRow += 4 - mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRow = new byte[bytesPerRow];
|
mRow = new byte[bytesPerRow];
|
||||||
|
|
||||||
mSrcX = 0;
|
mSrcX = 0;
|
||||||
@ -133,6 +135,7 @@ abstract class AbstractRLEDecoder implements Decoder {
|
|||||||
if (pByte < 0) {
|
if (pByte < 0) {
|
||||||
throw new EOFException("Premature end of file");
|
throw new EOFException("Premature end of file");
|
||||||
}
|
}
|
||||||
|
|
||||||
return pByte;
|
return pByte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/Base64Decoder.java
Executable file → Normal file
56
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/Base64Decoder.java
Executable file → Normal file
@ -43,7 +43,7 @@ import java.io.*;
|
|||||||
* @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/enc/Base64Decoder.java#2 $
|
* @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
|
* 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;
|
final static byte[] PEM_CONVERT_ARRAY;
|
||||||
private byte[] decode_buffer = new byte[4];
|
|
||||||
|
private byte[] mDecodeBuffer = new byte[4];
|
||||||
private ByteArrayOutputStream mWrapped;
|
private ByteArrayOutputStream mWrapped;
|
||||||
private Object mWrappedObject;
|
private Object mWrappedObject;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
PEM_CONVERT_ARRAY = new byte[256];
|
PEM_CONVERT_ARRAY = new byte[256];
|
||||||
|
|
||||||
for (int i = 0; i < 255; i++) {
|
for (int i = 0; i < 255; i++) {
|
||||||
PEM_CONVERT_ARRAY[i] = -1;
|
PEM_CONVERT_ARRAY[i] = -1;
|
||||||
}
|
}
|
||||||
@ -75,20 +77,23 @@ public class Base64Decoder implements Decoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int readFully(InputStream pStream, byte pBytes[],
|
protected static int readFully(final InputStream pStream, final byte pBytes[], final int pOffset, final int pLength)
|
||||||
int pOffset, int pLength) throws IOException {
|
throws IOException
|
||||||
|
{
|
||||||
for (int i = 0; i < pLength; i++) {
|
for (int i = 0; i < pLength; i++) {
|
||||||
int read = pStream.read();
|
int read = pStream.read();
|
||||||
|
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
return i != 0 ? i : -1;
|
return i != 0 ? i : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pBytes[i + pOffset] = (byte) read;
|
pBytes[i + pOffset] = (byte) read;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pLength;
|
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 {
|
throws IOException {
|
||||||
|
|
||||||
byte byte0 = -1;
|
byte byte0 = -1;
|
||||||
@ -105,37 +110,42 @@ public class Base64Decoder implements Decoder {
|
|||||||
// Skip line feeds
|
// Skip line feeds
|
||||||
do {
|
do {
|
||||||
read = pInput.read();
|
read = pInput.read();
|
||||||
|
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while (read == 10 || read == 13);
|
} while (read == 10 || read == 13);
|
||||||
|
|
||||||
decode_buffer[0] = (byte) read;
|
mDecodeBuffer[0] = (byte) read;
|
||||||
read = readFully(pInput, decode_buffer, 1, pLength - 1);
|
read = readFully(pInput, mDecodeBuffer, 1, pLength - 1);
|
||||||
|
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pLength > 3 && decode_buffer[3] == 61) {
|
|
||||||
pLength = 3;
|
int length = pLength;
|
||||||
}
|
|
||||||
if (pLength > 2 && decode_buffer[2] == 61) {
|
if (length > 3 && mDecodeBuffer[3] == 61) {
|
||||||
pLength = 2;
|
length = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pLength) {
|
if (length > 2 && mDecodeBuffer[2] == 61) {
|
||||||
|
length = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (length) {
|
||||||
case 4:
|
case 4:
|
||||||
byte3 = PEM_CONVERT_ARRAY[decode_buffer[3] & 255];
|
byte3 = PEM_CONVERT_ARRAY[mDecodeBuffer[3] & 255];
|
||||||
// fall through
|
// fall through
|
||||||
case 3:
|
case 3:
|
||||||
byte2 = PEM_CONVERT_ARRAY[decode_buffer[2] & 255];
|
byte2 = PEM_CONVERT_ARRAY[mDecodeBuffer[2] & 255];
|
||||||
// fall through
|
// fall through
|
||||||
case 2:
|
case 2:
|
||||||
byte1 = PEM_CONVERT_ARRAY[decode_buffer[1] & 255];
|
byte1 = PEM_CONVERT_ARRAY[mDecodeBuffer[1] & 255];
|
||||||
byte0 = PEM_CONVERT_ARRAY[decode_buffer[0] & 255];
|
byte0 = PEM_CONVERT_ARRAY[mDecodeBuffer[0] & 255];
|
||||||
// fall through
|
// fall through
|
||||||
default:
|
default:
|
||||||
switch (pLength) {
|
switch (length) {
|
||||||
case 2:
|
case 2:
|
||||||
pOutput.write((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
|
pOutput.write((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
|
||||||
break;
|
break;
|
||||||
@ -149,16 +159,18 @@ public class Base64Decoder implements Decoder {
|
|||||||
pOutput.write((byte) (byte2 << 6 & 192 | byte3 & 63));
|
pOutput.write((byte) (byte2 << 6 & 192 | byte3 & 63));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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 {
|
do {
|
||||||
int k = 72;
|
int k = 72;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i + 4 < k; i += 4) {
|
for (i = 0; i + 4 < k; i += 4) {
|
||||||
if(!decodeAtom(pInput, pOutput, 4)) {
|
if(!decodeAtom(pInput, pOutput, 4)) {
|
||||||
break;
|
break;
|
||||||
@ -169,17 +181,17 @@ public class Base64Decoder implements Decoder {
|
|||||||
break;
|
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) {
|
if (mWrappedObject != pBuffer) {
|
||||||
// NOTE: Array not cloned in FastByteArrayOutputStream
|
// NOTE: Array not cloned in FastByteArrayOutputStream
|
||||||
mWrapped = new FastByteArrayOutputStream(pBuffer);
|
mWrapped = new FastByteArrayOutputStream(pBuffer);
|
||||||
mWrappedObject = 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);
|
decodeBuffer(pStream, mWrapped, pBuffer.length);
|
||||||
|
|
||||||
return mWrapped.size();
|
return mWrapped.size();
|
||||||
|
19
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/Base64Encoder.java
Executable file → Normal file
19
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/Base64Encoder.java
Executable file → Normal file
@ -44,26 +44,37 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class Base64Encoder implements Encoder {
|
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
|
// TODO: Implement
|
||||||
// NOTE: This is impossible, given the current spec, as we need to either:
|
// NOTE: This is impossible, given the current spec, as we need to either:
|
||||||
// - buffer all data in the EncoderStream
|
// - buffer all data in the EncoderStream
|
||||||
// - or have flush/end method(s) in the Encoder
|
// - or have flush/end method(s) in the Encoder
|
||||||
// to ensure proper end of stream handling
|
// to ensure proper end of stream handling
|
||||||
|
|
||||||
|
int length = pLength;
|
||||||
int offset = pOffset;
|
int offset = pOffset;
|
||||||
|
|
||||||
// TODO: Temp impl, will only work for single writes
|
// TODO: Temp impl, will only work for single writes
|
||||||
while ((pBuffer.length - offset) > 0) {
|
while ((pBuffer.length - offset) > 0) {
|
||||||
byte a, b, c;
|
byte a, b, c;
|
||||||
|
|
||||||
if ((pBuffer.length - offset) > 2) {
|
if ((pBuffer.length - offset) > 2) {
|
||||||
pLength = 3;
|
length = 3;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pLength = pBuffer.length - offset;
|
length = pBuffer.length - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pLength) {
|
switch (length) {
|
||||||
case 1:
|
case 1:
|
||||||
a = pBuffer[offset];
|
a = pBuffer[offset];
|
||||||
b = 0;
|
b = 0;
|
||||||
|
24
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/DecoderStream.java
Executable file → Normal file
24
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/DecoderStream.java
Executable file → Normal file
@ -33,7 +33,7 @@ import java.io.IOException;
|
|||||||
import java.io.FilterInputStream;
|
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.
|
* stream.
|
||||||
* <p/>
|
* <p/>
|
||||||
* @see EncoderStream
|
* @see EncoderStream
|
||||||
@ -54,11 +54,11 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
* input stream specified by the {@code pStream} argument.
|
* input stream specified by the {@code pStream} argument.
|
||||||
*
|
*
|
||||||
* @param pStream the underlying input stream.
|
* @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
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public DecoderStream(InputStream pStream, Decoder pDecoder) {
|
public DecoderStream(final InputStream pStream, final Decoder pDecoder) {
|
||||||
super(pStream);
|
super(pStream);
|
||||||
mDecoder = pDecoder;
|
mDecoder = pDecoder;
|
||||||
mBuffer = new byte[1024];
|
mBuffer = new byte[1024];
|
||||||
@ -92,7 +92,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
|
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
|
||||||
((pOffset + pLength) > pBytes.length) || ((pOffset + 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) {
|
else if (pLength == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -106,6 +106,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
// Read until we have read pLength bytes, or have reached EOF
|
// Read until we have read pLength bytes, or have reached EOF
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int off = pOffset;
|
int off = pOffset;
|
||||||
|
|
||||||
while (pLength > count) {
|
while (pLength > count) {
|
||||||
int avail = mBufferLimit - mBufferPos;
|
int avail = mBufferLimit - mBufferPos;
|
||||||
|
|
||||||
@ -120,6 +121,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
// Copy as many bytes as possible
|
// Copy as many bytes as possible
|
||||||
int dstLen = Math.min(pLength - count, avail);
|
int dstLen = Math.min(pLength - count, avail);
|
||||||
System.arraycopy(mBuffer, mBufferPos, pBytes, off, dstLen);
|
System.arraycopy(mBuffer, mBufferPos, pBytes, off, dstLen);
|
||||||
|
|
||||||
mBufferPos += dstLen;
|
mBufferPos += dstLen;
|
||||||
|
|
||||||
// Update offset (rest)
|
// Update offset (rest)
|
||||||
@ -129,13 +131,6 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
count += dstLen;
|
count += dstLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
byte b = pBytes[pOffset + i];
|
|
||||||
System.out.print("0x" + Integer.toHexString(b & 0xff));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,11 +174,18 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
*/
|
*/
|
||||||
protected int fill() throws IOException {
|
protected int fill() throws IOException {
|
||||||
int read = mDecoder.decode(in, mBuffer);
|
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;
|
mBufferPos = 0;
|
||||||
|
|
||||||
if (read == 0) {
|
if (read == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/Encoder.java
Executable file → Normal file
0
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/Encoder.java
Executable file → Normal file
18
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/EncoderStream.java
Executable file → Normal file
18
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/EncoderStream.java
Executable file → Normal file
@ -55,9 +55,9 @@ public final class EncoderStream extends FilterOutputStream {
|
|||||||
* underlying output stream.
|
* underlying output stream.
|
||||||
*
|
*
|
||||||
* @param pStream the 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);
|
this(pStream, pEncoder, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,11 +66,11 @@ public final class EncoderStream extends FilterOutputStream {
|
|||||||
* underlying output stream.
|
* underlying output stream.
|
||||||
*
|
*
|
||||||
* @param pStream the 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
|
* @param pFlushOnWrite if {@code true}, calls to the byte-array
|
||||||
* {@code write} methods will automatically flush the buffer.
|
* {@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);
|
super(pStream);
|
||||||
|
|
||||||
mEncoder = pEncoder;
|
mEncoder = pEncoder;
|
||||||
@ -94,12 +94,13 @@ public final class EncoderStream extends FilterOutputStream {
|
|||||||
if (mBufferPos != 0) {
|
if (mBufferPos != 0) {
|
||||||
// Make sure all remaining data in buffer is written to the stream
|
// Make sure all remaining data in buffer is written to the stream
|
||||||
mEncoder.encode(out, mBuffer, 0, mBufferPos);
|
mEncoder.encode(out, mBuffer, 0, mBufferPos);
|
||||||
|
|
||||||
// Reset buffer
|
// Reset buffer
|
||||||
mBufferPos = 0;
|
mBufferPos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void write(byte[] pBytes) throws IOException {
|
public final void write(final byte[] pBytes) throws IOException {
|
||||||
write(pBytes, 0, pBytes.length);
|
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
|
// 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
|
// that the encoder can't buffer. In that case, the encoder should probably
|
||||||
// tell the EncoderStream how large buffer it prefers...
|
// 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) {
|
if (!mFlushOnWrite && mBufferPos + pLength < mBuffer.length) {
|
||||||
// Buffer data
|
// Buffer data
|
||||||
System.arraycopy(pBytes, pOffset, mBuffer, mBufferPos, pLength);
|
System.arraycopy(pBytes, pOffset, mBuffer, mBufferPos, pLength);
|
||||||
mBufferPos += pLength;
|
mBufferPos += pLength;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Encode data allready in the buffer
|
// Encode data already in the buffer
|
||||||
if (mBufferPos != 0) {
|
if (mBufferPos != 0) {
|
||||||
encodeBuffer();
|
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) {
|
if (mBufferPos >= mBuffer.length - 1) {
|
||||||
encodeBuffer(); // Resets mBufferPos to 0
|
encodeBuffer(); // Resets mBufferPos to 0
|
||||||
}
|
}
|
||||||
|
|
||||||
mBuffer[mBufferPos++] = (byte) pByte;
|
mBuffer[mBufferPos++] = (byte) pByte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/PackBits16Decoder.java
Executable file → Normal file
23
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/PackBits16Decoder.java
Executable file → Normal file
@ -62,31 +62,31 @@ public final class PackBits16Decoder implements Decoder {
|
|||||||
/**
|
/**
|
||||||
* Creates a {@code PackBitsDecoder}.
|
* Creates a {@code PackBitsDecoder}.
|
||||||
* <p/>
|
* <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
|
* a compressed run, instead of a no-op, it's possible to disable no-ops
|
||||||
* for compatibility.
|
* for compatibility.
|
||||||
* Should be used with caution, even though, most known encoders never write
|
* Should be used with caution, even though, most known encoders never write
|
||||||
* no-ops in the compressed streams.
|
* 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;
|
mDisableNoop = pDisableNoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes bytes from the given input stream, to the given buffer.
|
* 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)
|
* @param pBuffer a byte array, minimum 128 (or 129 if no-op is disabled)
|
||||||
* bytes long
|
* bytes long
|
||||||
* @return The number of bytes decoded
|
* @return The number of bytes decoded
|
||||||
*
|
*
|
||||||
* @throws java.io.IOException
|
* @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) {
|
if (mEOF) {
|
||||||
throw new EOFException("Unexpected end of PackBits stream");
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read = 0;
|
int read = 0;
|
||||||
@ -94,6 +94,7 @@ public final class PackBits16Decoder implements Decoder {
|
|||||||
|
|
||||||
while (read < max) {
|
while (read < max) {
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (mSplitRun) {
|
if (mSplitRun) {
|
||||||
// Continue run
|
// Continue run
|
||||||
n = mLeftOfRun;
|
n = mLeftOfRun;
|
||||||
@ -149,24 +150,30 @@ public final class PackBits16Decoder implements Decoder {
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte readByte(InputStream pStream) throws IOException {
|
private static byte readByte(final InputStream pStream) throws IOException {
|
||||||
int read = pStream.read();
|
int read = pStream.read();
|
||||||
|
|
||||||
if (read < 0) {
|
if (read < 0) {
|
||||||
throw new EOFException("Unexpected end of PackBits stream");
|
throw new EOFException("Unexpected end of PackBits stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (byte) read;
|
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) {
|
if (pLength < 0) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
int read = 0;
|
int read = 0;
|
||||||
|
|
||||||
while (read < pLength) {
|
while (read < pLength) {
|
||||||
int count = pStream.read(pBuffer, pOffset + read, pLength - read);
|
int count = pStream.read(pBuffer, pOffset + read, pLength - read);
|
||||||
|
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
throw new EOFException("Unexpected end of PackBits stream");
|
throw new EOFException("Unexpected end of PackBits stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
read += count;
|
read += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/PackBitsDecoder.java
Executable file → Normal file
27
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/PackBitsDecoder.java
Executable file → Normal file
@ -69,9 +69,7 @@ public final class PackBitsDecoder implements Decoder {
|
|||||||
private boolean mSplitRun;
|
private boolean mSplitRun;
|
||||||
private boolean mEOF;
|
private boolean mEOF;
|
||||||
|
|
||||||
/**
|
/** Creates a {@code PackBitsDecoder}. */
|
||||||
* Creates a {@code PackBitsDecoder}.
|
|
||||||
*/
|
|
||||||
public PackBitsDecoder() {
|
public PackBitsDecoder() {
|
||||||
this(false);
|
this(false);
|
||||||
}
|
}
|
||||||
@ -79,31 +77,31 @@ public final class PackBitsDecoder implements Decoder {
|
|||||||
/**
|
/**
|
||||||
* Creates a {@code PackBitsDecoder}.
|
* Creates a {@code PackBitsDecoder}.
|
||||||
* <p/>
|
* <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
|
* a compressed run, instead of a no-op, it's possible to disable no-ops
|
||||||
* for compatibility.
|
* for compatibility.
|
||||||
* Should be used with caution, even though, most known encoders never write
|
* Should be used with caution, even though, most known encoders never write
|
||||||
* no-ops in the compressed streams.
|
* 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;
|
mDisableNoop = pDisableNoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes bytes from the given input stream, to the given buffer.
|
* 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)
|
* @param pBuffer a byte array, minimum 128 (or 129 if no-op is disabled)
|
||||||
* bytes long
|
* bytes long
|
||||||
* @return The number of bytes decoded
|
* @return The number of bytes decoded
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public int decode(InputStream pStream, byte[] pBuffer) throws IOException {
|
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
|
||||||
if (mEOF) {
|
if (mEOF) {
|
||||||
throw new EOFException("Unexpected end of PackBits stream");
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read = 0;
|
int read = 0;
|
||||||
@ -111,6 +109,7 @@ public final class PackBitsDecoder implements Decoder {
|
|||||||
|
|
||||||
while (read < max) {
|
while (read < max) {
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (mSplitRun) {
|
if (mSplitRun) {
|
||||||
// Continue run
|
// Continue run
|
||||||
n = mLeftOfRun;
|
n = mLeftOfRun;
|
||||||
@ -164,24 +163,30 @@ public final class PackBitsDecoder implements Decoder {
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte readByte(InputStream pStream) throws IOException {
|
private static byte readByte(final InputStream pStream) throws IOException {
|
||||||
int read = pStream.read();
|
int read = pStream.read();
|
||||||
|
|
||||||
if (read < 0) {
|
if (read < 0) {
|
||||||
throw new EOFException("Unexpected end of PackBits stream");
|
throw new EOFException("Unexpected end of PackBits stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (byte) read;
|
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) {
|
if (pLength < 0) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
int read = 0;
|
int read = 0;
|
||||||
|
|
||||||
while (read < pLength) {
|
while (read < pLength) {
|
||||||
int count = pStream.read(pBuffer, pOffset + read, pLength - read);
|
int count = pStream.read(pBuffer, pOffset + read, pLength - read);
|
||||||
|
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
throw new EOFException("Unexpected end of PackBits stream");
|
throw new EOFException("Unexpected end of PackBits stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
read += count;
|
read += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/RLE4Decoder.java
Executable file → Normal file
5
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/RLE4Decoder.java
Executable file → Normal file
@ -52,6 +52,7 @@ final class RLE4Decoder extends AbstractRLEDecoder {
|
|||||||
while (mSrcY >= 0) {
|
while (mSrcY >= 0) {
|
||||||
int byte1 = pInput.read();
|
int byte1 = pInput.read();
|
||||||
int byte2 = checkEOF(pInput.read());
|
int byte2 = checkEOF(pInput.read());
|
||||||
|
|
||||||
if (byte1 == 0x00) {
|
if (byte1 == 0x00) {
|
||||||
switch (byte2) {
|
switch (byte2) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
@ -102,6 +103,7 @@ final class RLE4Decoder extends AbstractRLEDecoder {
|
|||||||
mRow[mSrcX++] = (byte) byte2;
|
mRow[mSrcX++] = (byte) byte2;
|
||||||
byte1 -= 2;
|
byte1 -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (byte1 == 1) {
|
if (byte1 == 1) {
|
||||||
// TODO: Half byte alignment? Seems to be ok...
|
// TODO: Half byte alignment? Seems to be ok...
|
||||||
mRow[mSrcX++] = (byte) (byte2 & 0xf0);
|
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 we're done with a complete row, copy the data
|
||||||
if (mSrcX == mRow.length) {
|
if (mSrcX == mRow.length) {
|
||||||
|
|
||||||
// Move to new position, either absolute (delta) or next line
|
// Move to new position, either absolute (delta) or next line
|
||||||
if (deltaX != 0 || deltaY != 0) {
|
if (deltaX != 0 || deltaY != 0) {
|
||||||
mSrcX = (deltaX + 1) / 2;
|
mSrcX = (deltaX + 1) / 2;
|
||||||
|
|
||||||
if (deltaY > mSrcY) {
|
if (deltaY > mSrcY) {
|
||||||
mSrcY = deltaY;
|
mSrcY = deltaY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
deltaX = 0;
|
deltaX = 0;
|
||||||
deltaY = 0;
|
deltaY = 0;
|
||||||
}
|
}
|
||||||
|
1
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/RLE8Decoder.java
Executable file → Normal file
1
twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/RLE8Decoder.java
Executable file → Normal file
@ -52,6 +52,7 @@ final class RLE8Decoder extends AbstractRLEDecoder {
|
|||||||
while (mSrcY >= 0) {
|
while (mSrcY >= 0) {
|
||||||
int byte1 = pInput.read();
|
int byte1 = pInput.read();
|
||||||
int byte2 = checkEOF(pInput.read());
|
int byte2 = checkEOF(pInput.read());
|
||||||
|
|
||||||
if (byte1 == 0x00) {
|
if (byte1 == 0x00) {
|
||||||
switch (byte2) {
|
switch (byte2) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
|
6
twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/enc/Base64EncoderTestCase.java
Executable file → Normal file
6
twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/enc/Base64EncoderTestCase.java
Executable file → Normal file
@ -20,14 +20,14 @@ public class Base64EncoderTestCase extends EncoderAbstractTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testNegativeEncode() throws IOException {
|
public void testNegativeEncode() throws IOException {
|
||||||
Encoder base64 = createEncoder();
|
Encoder encoder = createEncoder();
|
||||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
base64.encode(bytes, new byte[1], 2, 1);
|
encoder.encode(bytes, new byte[1], 2, 1);
|
||||||
fail("wrong index should throw IndexOutOfBoundsException");
|
fail("wrong index should throw IndexOutOfBoundsException");
|
||||||
}
|
}
|
||||||
catch (IndexOutOfBoundsException e) {
|
catch (IndexOutOfBoundsException expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/enc/DecoderAbstractTestCase.java
Executable file → Normal file
28
twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/enc/DecoderAbstractTestCase.java
Executable file → Normal file
@ -1,11 +1,7 @@
|
|||||||
package com.twelvemonkeys.io.enc;
|
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.io.FileUtil;
|
||||||
|
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -86,14 +82,34 @@ public abstract class DecoderAbstractTestCase extends ObjectAbstractTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void testStreams() throws Exception {
|
public final void testStreams() throws Exception {
|
||||||
for (int i = 0; i < 100; ++i) {
|
for (int i = 0; i < 100; i++) {
|
||||||
|
try {
|
||||||
runStreamTest(i);
|
runStreamTest(i);
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
fail(e.getMessage() + ": " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 100; i < 2000; i += 250) {
|
for (int i = 100; i < 2000; i += 250) {
|
||||||
|
try {
|
||||||
runStreamTest(i);
|
runStreamTest(i);
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
fail(e.getMessage() + ": " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 2000; i < 80000; i += 1000) {
|
for (int i = 2000; i < 80000; i += 1000) {
|
||||||
|
try {
|
||||||
runStreamTest(i);
|
runStreamTest(i);
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
fail(e.getMessage() + ": " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
85
twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/enc/EncoderAbstractTestCase.java
Executable file → Normal file
85
twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/enc/EncoderAbstractTestCase.java
Executable file → Normal file
@ -1,11 +1,7 @@
|
|||||||
package com.twelvemonkeys.io.enc;
|
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.io.FileUtil;
|
||||||
|
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -31,58 +27,99 @@ public abstract class EncoderAbstractTestCase extends ObjectAbstractTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void testNullEncode() throws IOException {
|
public final void testNullEncode() throws IOException {
|
||||||
Encoder base64 = createEncoder();
|
Encoder encoder = createEncoder();
|
||||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
base64.encode(bytes, null, 0, 1);
|
encoder.encode(bytes, null, 0, 1);
|
||||||
fail("null should throw NullPointerException");
|
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];
|
byte[] bytes = new byte[pLength];
|
||||||
RANDOM.nextBytes(bytes);
|
RANDOM.nextBytes(bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runStreamTest(int pLength) throws Exception {
|
private void runStreamTest(final int pLength) throws Exception {
|
||||||
byte[] data = createData(pLength);
|
byte[] data = createData(pLength);
|
||||||
ByteArrayOutputStream out_bytes = new ByteArrayOutputStream();
|
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
|
||||||
OutputStream out = new EncoderStream(out_bytes, createEncoder(), true);
|
OutputStream out = new EncoderStream(outBytes, createEncoder(), true);
|
||||||
|
|
||||||
|
try {
|
||||||
out.write(data);
|
out.write(data);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
out.close();
|
out.close();
|
||||||
byte[] encoded = out_bytes.toByteArray();
|
}
|
||||||
|
|
||||||
|
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()));
|
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createCompatibleDecoder()));
|
||||||
assertTrue(Arrays.equals(data, decoded));
|
assertTrue(Arrays.equals(data, decoded));
|
||||||
|
|
||||||
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createCompatibleDecoder());
|
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createCompatibleDecoder());
|
||||||
out_bytes = new ByteArrayOutputStream();
|
outBytes = 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);
|
|
||||||
|
|
||||||
out_bytes.close();
|
try {
|
||||||
|
FileUtil.copy(in, outBytes);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
outBytes.close();
|
||||||
in.close();
|
in.close();
|
||||||
decoded = out_bytes.toByteArray();
|
}
|
||||||
|
|
||||||
|
decoded = outBytes.toByteArray();
|
||||||
assertTrue(Arrays.equals(data, decoded));
|
assertTrue(Arrays.equals(data, decoded));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void testStreams() throws Exception {
|
public final void testStreams() throws Exception {
|
||||||
for (int i = 0; i < 100; ++i) {
|
for (int i = 0; i < 100; i++) {
|
||||||
|
try {
|
||||||
runStreamTest(i);
|
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) {
|
for (int i = 100; i < 2000; i += 250) {
|
||||||
|
try {
|
||||||
runStreamTest(i);
|
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) {
|
for (int i = 2000; i < 80000; i += 1000) {
|
||||||
|
try {
|
||||||
runStreamTest(i);
|
runStreamTest(i);
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
fail(e.getMessage() + ": " + i);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
fail(e.getMessage() + ": " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDUtil.java
Executable file → Normal file
5
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDUtil.java
Executable file → Normal file
@ -30,12 +30,12 @@ package com.twelvemonkeys.imageio.plugins.psd;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import com.twelvemonkeys.io.enc.DecoderStream;
|
import com.twelvemonkeys.io.enc.DecoderStream;
|
||||||
import com.twelvemonkeys.io.enc.InflateDecoder;
|
|
||||||
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
||||||
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PSDUtil
|
* PSDUtil
|
||||||
@ -81,7 +81,8 @@ final class PSDUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static DataInputStream createZipStream(final ImageInputStream pInput, int pLength) {
|
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) {
|
static DataInputStream createZipPredictorStream(final ImageInputStream pInput, int pLength) {
|
||||||
|
@ -36,31 +36,55 @@ import java.util.zip.Deflater;
|
|||||||
* {@code Encoder} implementation for standard DEFLATE encoding.
|
* {@code Encoder} implementation for standard DEFLATE encoding.
|
||||||
* <p/>
|
* <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 Deflater
|
||||||
* @see InflateDecoder
|
* @see InflateDecoder
|
||||||
* @see java.util.zip.DeflaterOutputStream
|
* @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 Deflater mDeflater;
|
||||||
|
private final byte[] mBuffer = new byte[1024];
|
||||||
|
|
||||||
public DeflateEncoder() {
|
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) {
|
if (pDeflater == null) {
|
||||||
throw new IllegalArgumentException("deflater == null");
|
throw new IllegalArgumentException("deflater == null");
|
||||||
}
|
}
|
||||||
|
|
||||||
mDeflater = pDeflater;
|
mDeflater = pDeflater;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
throw new InternalError("not implemented: encode()"); // TODO: Implement
|
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();
|
||||||
|
// }
|
||||||
|
}
|
@ -47,7 +47,7 @@ import java.util.zip.Inflater;
|
|||||||
* @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/enc/InflateDecoder.java#2 $
|
* @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;
|
private final Inflater mInflater;
|
||||||
|
|
||||||
@ -66,25 +66,29 @@ public final class InflateDecoder implements Decoder {
|
|||||||
*
|
*
|
||||||
* @param pInflater the inflater instance to use
|
* @param pInflater the inflater instance to use
|
||||||
*/
|
*/
|
||||||
public InflateDecoder(Inflater pInflater) {
|
public InflateDecoder(final Inflater pInflater) {
|
||||||
if (pInflater == null) {
|
if (pInflater == null) {
|
||||||
throw new IllegalArgumentException("inflater == null");
|
throw new IllegalArgumentException("inflater == null");
|
||||||
}
|
}
|
||||||
|
|
||||||
mInflater = pInflater;
|
mInflater = pInflater;
|
||||||
mBuffer = new byte[1024];
|
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 {
|
try {
|
||||||
int decoded;
|
int decoded;
|
||||||
|
|
||||||
while ((decoded = mInflater.inflate(pBuffer, 0, pBuffer.length)) == 0) {
|
while ((decoded = mInflater.inflate(pBuffer, 0, pBuffer.length)) == 0) {
|
||||||
if (mInflater.finished() || mInflater.needsDictionary()) {
|
if (mInflater.finished() || mInflater.needsDictionary()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInflater.needsInput()) {
|
if (mInflater.needsInput()) {
|
||||||
fill(pStream);
|
fill(pStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
catch (DataFormatException e) {
|
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);
|
int available = pStream.read(mBuffer, 0, mBuffer.length);
|
||||||
|
|
||||||
if (available == -1) {
|
if (available == -1) {
|
||||||
throw new EOFException("Unexpected end of ZLIB stream");
|
throw new EOFException("Unexpected end of ZLIB stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
mInflater.setInput(mBuffer, 0, available);
|
mInflater.setInput(mBuffer, 0, available);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -38,7 +38,7 @@ import java.io.IOException;
|
|||||||
* @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/enc/LZWDecoder.java#2 $
|
* @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 {
|
public int decode(InputStream pStream, byte[] pBuffer) throws IOException {
|
||||||
return 0; // TODO: Implement
|
return 0; // TODO: Implement
|
||||||
// TODO: We probably need a GIF specific subclass
|
// TODO: We probably need a GIF specific subclass
|
@ -38,7 +38,7 @@ import java.io.IOException;
|
|||||||
* @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/enc/LZWEncoder.java#2 $
|
* @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 {
|
public void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
// TODO: We probably need a GIF specific subclass
|
// TODO: We probably need a GIF specific subclass
|
@ -1,18 +1,13 @@
|
|||||||
package com.twelvemonkeys.io.enc;
|
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/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @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/test/java/com/twelvemonkeys/io/enc/DeflateDecoderTestCase.java#1 $
|
* @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() {
|
protected Encoder createEncoder() {
|
||||||
return new DeflateEncoder();
|
return new DeflateEncoder();
|
||||||
}
|
}
|
@ -1,10 +1,5 @@
|
|||||||
package com.twelvemonkeys.io.enc;
|
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
|
* InflateEncoderTest
|
||||||
* <p/>
|
* <p/>
|
Loading…
x
Reference in New Issue
Block a user