blob: b039c9d4f21e2cff851dae1431794fb2c968d6d5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.imaging.common;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import org.apache.commons.imaging.ImageReadException;
public class BinaryInputStream extends InputStream implements BinaryConstants
{
protected boolean debug = false;
public final void setDebug(boolean b)
{
debug = b;
}
public final boolean getDebug()
{
return debug;
}
private final InputStream is;
public BinaryInputStream(byte bytes[], int byteOrder)
{
this.byteOrder = byteOrder;
this.is = new ByteArrayInputStream(bytes);
}
public BinaryInputStream(InputStream is, int byteOrder)
{
this.byteOrder = byteOrder;
this.is = is;
}
public BinaryInputStream(InputStream is)
{
this.is = is;
}
// default byte order for Java, many file formats.
private int byteOrder = BYTE_ORDER_NETWORK;
protected void setByteOrder(int a, int b) throws ImageReadException
{
if (a != b)
throw new ImageReadException("Byte Order bytes don't match (" + a
+ ", " + b + ").");
if (a == BYTE_ORDER_MOTOROLA)
byteOrder = a;
else if (a == BYTE_ORDER_INTEL)
byteOrder = a;
else
throw new ImageReadException("Unknown Byte Order hint: " + a);
}
protected void setByteOrder(int byteOrder)
{
this.byteOrder = byteOrder;
}
protected int getByteOrder()
{
return byteOrder;
}
@Override
public int read() throws IOException
{
return is.read();
}
protected final int convertByteArrayToInt(String name, byte bytes[])
{
return convertByteArrayToInt(name, bytes, byteOrder);
}
public final int convertByteArrayToShort(String name, byte bytes[])
{
return convertByteArrayToShort(name, bytes, byteOrder);
}
public final int convertByteArrayToShort(String name, int start,
byte bytes[])
{
return convertByteArrayToShort(name, start, bytes, byteOrder);
}
public final int read4Bytes(String name, String exception)
throws IOException
{
return read4Bytes(name, exception, byteOrder);
}
public final int read3Bytes(String name, String exception)
throws IOException
{
return read3Bytes(name, exception, byteOrder);
}
public final int read2Bytes(String name, String exception)
throws IOException
{
return read2Bytes(name, exception, byteOrder);
}
protected final void readRandomBytes() throws IOException
{
for (int counter = 0; counter < 100; counter++)
{
readByte("" + counter, "Random Data");
}
}
public final void debugNumber(String msg, int data)
{
debugNumber(msg, data, 1);
}
public final void debugNumber(String msg, int data, int bytes)
{
System.out.print(msg + ": " + data + " (");
int byteData = data;
for (int i = 0; i < bytes; i++)
{
if (i > 0)
System.out.print(",");
int singleByte = 0xff & byteData;
System.out.print((char) singleByte + " [" + singleByte + "]");
byteData >>= 8;
}
System.out.println(") [0x" + Integer.toHexString(data) + ", "
+ Integer.toBinaryString(data) + "]");
}
public final void readAndVerifyBytes(byte expected[], String exception)
throws ImageReadException, IOException
{
for (int i = 0; i < expected.length; i++)
{
int data = is.read();
byte b = (byte) (0xff & data);
if ((data < 0) || (b != expected[i]))
{
System.out.println("i" + ": " + i);
this.debugByteArray("expected", expected);
debugNumber("data[" + i + "]", b);
// debugNumber("expected[" + i + "]", expected[i]);
throw new ImageReadException(exception);
}
}
}
protected final void readAndVerifyBytes(String name, byte expected[],
String exception) throws ImageReadException, IOException
{
byte bytes[] = readByteArray(name, expected.length, exception);
for (int i = 0; i < expected.length; i++)
{
if (bytes[i] != expected[i])
{
System.out.println("i" + ": " + i);
debugNumber("bytes[" + i + "]", bytes[i]);
debugNumber("expected[" + i + "]", expected[i]);
throw new ImageReadException(exception);
}
}
}
public final void skipBytes(int length, String exception)
throws IOException
{
long total = 0;
while (length != total)
{
long skipped = is.skip(length - total);
if (skipped < 1)
throw new IOException(exception + " (" + skipped + ")");
total += skipped;
}
}
protected final void scanForByte(byte value) throws IOException
{
int count = 0;
for (int i = 0; count < 3; i++)
// while(count<3)
{
int b = is.read();
if (b < 0)
return;
if ((0xff & b) == value)
{
System.out.println("\t" + i + ": match.");
count++;
}
}
}
public final byte readByte(String name, String exception)
throws IOException
{
int result = is.read();
if ((result < 0))
{
System.out.println(name + ": " + result);
throw new IOException(exception);
}
if (debug)
debugNumber(name, result);
return (byte) (0xff & result);
}
protected final RationalNumber[] convertByteArrayToRationalArray(
String name, byte bytes[], int start, int length, int byteOrder)
{
int expectedLength = start + length * 8;
if (bytes.length < expectedLength)
{
System.out.println(name + ": expected length: " + expectedLength
+ ", actual length: " + bytes.length);
return null;
}
RationalNumber result[] = new RationalNumber[length];
for (int i = 0; i < length; i++)
{
result[i] = convertByteArrayToRational(name, bytes, start + i * 8,
byteOrder);
}
return result;
}
protected final RationalNumber convertByteArrayToRational(String name,
byte bytes[], int byteOrder)
{
return convertByteArrayToRational(name, bytes, 0, byteOrder);
}
protected final RationalNumber convertByteArrayToRational(String name,
byte bytes[], int start, int byteOrder)
{
int numerator = convertByteArrayToInt(name, bytes, start + 0, 4,
byteOrder);
int divisor = convertByteArrayToInt(name, bytes, start + 4, 4,
byteOrder);
return new RationalNumber(numerator, divisor);
}
protected final int convertByteArrayToInt(String name, byte bytes[],
int byteOrder)
{
return convertByteArrayToInt(name, bytes, 0, 4, byteOrder);
}
protected final int convertByteArrayToInt(String name, byte bytes[],
int start, int length, int byteOrder)
{
byte byte0 = bytes[start + 0];
byte byte1 = bytes[start + 1];
byte byte2 = bytes[start + 2];
byte byte3 = 0;
if (length == 4)
byte3 = bytes[start + 3];
// return convert4BytesToInt(name, byte0, byte1, byte2, byte3,
// byteOrder);
int result;
if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
result = ((0xff & byte0) << 24) + ((0xff & byte1) << 16)
+ ((0xff & byte2) << 8) + ((0xff & byte3) << 0);
// result = (( byte0) << 24) + ((byte1) << 16)
// + (( byte2) << 8) + (( byte3) << 0);
else
// intel, little endian
result = ((0xff & byte3) << 24) + ((0xff & byte2) << 16)
+ ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
// result = (( byte3) << 24) + (( byte2) << 16)
// + (( byte1) << 8) + (( byte0) << 0);
if (debug)
debugNumber(name, result, 4);
return result;
}
protected final int[] convertByteArrayToIntArray(String name, byte bytes[],
int start, int length, int byteOrder)
{
int expectedLength = start + length * 4;
if (bytes.length < expectedLength)
{
System.out.println(name + ": expected length: " + expectedLength
+ ", actual length: " + bytes.length);
return null;
}
int result[] = new int[length];
for (int i = 0; i < length; i++)
{
result[i] = convertByteArrayToInt(name, bytes, start + i * 4, 4,
byteOrder);
}
return result;
}
protected final int convertByteArrayToShort(String name, byte bytes[],
int byteOrder)
{
return convertByteArrayToShort(name, 0, bytes, byteOrder);
}
protected final int convertByteArrayToShort(String name, int start,
byte bytes[], int byteOrder)
{
byte byte0 = bytes[start + 0];
byte byte1 = bytes[start + 1];
// return convert2BytesToShort(name, byte0, byte1, byteOrder);
int result;
if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
result = ((0xff & byte0) << 8) + ((0xff & byte1) << 0);
else
// intel, little endian
result = ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
if (debug)
debugNumber(name, result, 2);
return result;
}
protected final int[] convertByteArrayToShortArray(String name,
byte bytes[], int start, int length, int byteOrder)
{
int expectedLength = start + length * 2;
if (bytes.length < expectedLength)
{
System.out.println(name + ": expected length: " + expectedLength
+ ", actual length: " + bytes.length);
return null;
}
int result[] = new int[length];
for (int i = 0; i < length; i++)
{
result[i] = convertByteArrayToShort(name, start + i * 2, bytes,
byteOrder);
// byte byte0 = bytes[start + i * 2];
// byte byte1 = bytes[start + i * 2 + 1];
// result[i] = convertBytesToShort(name, byte0, byte1, byteOrder);
}
return result;
}
public final byte[] readByteArray(String name, int length, String exception)
throws IOException
{
byte result[] = new byte[length];
int read = 0;
while (read < length)
{
int count = is.read(result, read, length - read);
if (count < 1)
throw new IOException(exception);
read += count;
}
if (debug)
{
for (int i = 0; ((i < length) && (i < 150)); i++)
{
debugNumber(name + " (" + i + ")", 0xff & result[i]);
}
}
return result;
}
protected final void debugByteArray(String name, byte bytes[])
{
System.out.println(name + ": " + bytes.length);
for (int i = 0; ((i < bytes.length) && (i < 50)); i++)
{
debugNumber(name + " (" + i + ")", bytes[i]);
}
}
protected final void debugNumberArray(String name, int numbers[], int length)
{
System.out.println(name + ": " + numbers.length);
for (int i = 0; ((i < numbers.length) && (i < 50)); i++)
{
debugNumber(name + " (" + i + ")", numbers[i], length);
}
}
public final byte[] readBytearray(String name, byte bytes[], int start,
int count)
{
if (bytes.length < (start + count))
return null;
byte result[] = new byte[count];
System.arraycopy(bytes, start, result, 0, count);
if (debug)
debugByteArray(name, result);
return result;
}
public final byte[] readByteArray(int length, String error)
throws ImageReadException, IOException
{
boolean verbose = false;
boolean strict = true;
return readByteArray(length, error, verbose, strict);
}
public final byte[] readByteArray(int length, String error,
boolean verbose, boolean strict) throws ImageReadException,
IOException
{
byte bytes[] = new byte[length];
int total = 0;
int read;
while ((read = read(bytes, total, length - total)) > 0)
total += read;
if (total < length)
{
if (strict)
throw new ImageReadException(error);
else if(verbose)
System.out.println(error);
return null;
}
return bytes;
}
protected final byte[] getBytearrayTail(String name, byte bytes[], int count)
{
return readBytearray(name, bytes, count, bytes.length - count);
}
protected final byte[] getBytearrayHead(String name, byte bytes[], int count)
{
return readBytearray(name, bytes, 0, bytes.length - count);
}
public final boolean compareByteArrays(byte a[], int aStart, byte b[],
int bStart, int length)
{
if (a.length < (aStart + length))
return false;
if (b.length < (bStart + length))
return false;
for (int i = 0; i < length; i++)
{
if (a[aStart + i] != b[bStart + i])
{
debugNumber("a[" + (aStart + i) + "]", a[aStart + i]);
debugNumber("b[" + (bStart + i) + "]", b[bStart + i]);
return false;
}
}
return true;
}
protected final int read4Bytes(String name, String exception, int byteOrder)
throws IOException
{
int size = 4;
byte bytes[] = new byte[size];
int read = 0;
while (read < size)
{
int count = is.read(bytes, read, size - read);
if (count < 1)
throw new IOException(exception);
read += count;
}
return convertByteArrayToInt(name, bytes, byteOrder);
}
protected final int read3Bytes(String name, String exception, int byteOrder)
throws IOException
{
int size = 3;
byte bytes[] = new byte[size];
int read = 0;
while (read < size)
{
int count = is.read(bytes, read, size - read);
if (count < 1)
throw new IOException(exception);
read += count;
}
return convertByteArrayToInt(name, bytes, 0, 3, byteOrder);
}
protected final int read2Bytes(String name, String exception, int byteOrder)
throws IOException
{
int size = 2;
byte bytes[] = new byte[size];
int read = 0;
while (read < size)
{
int count = is.read(bytes, read, size - read);
if (count < 1)
throw new IOException(exception);
read += count;
}
return convertByteArrayToShort(name, bytes, byteOrder);
}
public final int read1ByteInteger(String exception)
throws ImageReadException, IOException
{
int byte0 = is.read();
if (byte0 < 0)
throw new ImageReadException(exception);
return 0xff & byte0;
}
public final int read2ByteInteger(String exception)
throws ImageReadException, IOException
{
int byte0 = is.read();
int byte1 = is.read();
if (byte0 < 0 || byte1 < 0)
throw new ImageReadException(exception);
if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
return ((0xff & byte0) << 8) + ((0xff & byte1) << 0);
else
// intel, little endian
return ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
}
public final int read4ByteInteger(String exception)
throws ImageReadException, IOException
{
int byte0 = is.read();
int byte1 = is.read();
int byte2 = is.read();
int byte3 = is.read();
if (byte0 < 0 || byte1 < 0 || byte2 < 0 || byte3 < 0)
throw new ImageReadException(exception);
if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
return ((0xff & byte0) << 24) + ((0xff & byte1) << 16)
+ ((0xff & byte2) << 8) + ((0xff & byte3) << 0);
else
// intel, little endian
return ((0xff & byte3) << 24) + ((0xff & byte2) << 16)
+ ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
}
protected final void printCharQuad(String msg, int i)
{
System.out.println(msg + ": '" + (char) (0xff & (i >> 24))
+ (char) (0xff & (i >> 16)) + (char) (0xff & (i >> 8))
+ (char) (0xff & (i >> 0)) + "'");
}
protected final void printByteBits(String msg, byte i)
{
System.out.println(msg + ": '" + Integer.toBinaryString(0xff & i));
}
protected final static int charsToQuad(char c1, char c2, char c3, char c4)
{
return (((0xff & c1) << 24) | ((0xff & c2) << 16) | ((0xff & c3) << 8) | ((0xff & c4) << 0));
}
public final int findNull(byte src[])
{
return findNull(src, 0);
}
public final int findNull(byte src[], int start)
{
for (int i = start; i < src.length; i++)
{
if (src[i] == 0)
return i;
}
return -1;
}
protected final byte[] getRAFBytes(RandomAccessFile raf, long pos,
int length, String exception) throws IOException
{
byte result[] = new byte[length];
if (debug)
{
System.out.println("getRAFBytes pos" + ": " + pos);
System.out.println("getRAFBytes length" + ": " + length);
}
raf.seek(pos);
int read = 0;
while (read < length)
{
int count = raf.read(result, read, length - read);
if (count < 1)
throw new IOException(exception);
read += count;
}
return result;
}
protected void skipBytes(int length) throws IOException
{
skipBytes(length, "Couldn't skip bytes");
}
}