You are viewing a plain text version of this content. The canonical link for it is here.
Posted to sanselan-commits@incubator.apache.org by cm...@apache.org on 2007/11/17 21:58:40 UTC
svn commit: r596008 [3/15] - in /incubator/sanselan/trunk/src:
main/java/org/apache/sanselan/ main/java/org/apache/sanselan/color/
main/java/org/apache/sanselan/common/
main/java/org/apache/sanselan/common/byteSources/
main/java/org/apache/sanselan/com...
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileFunctions.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileFunctions.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileFunctions.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileFunctions.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,1032 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+
+import org.cmc.sanselan.ImageReadException;
+import org.cmc.sanselan.ImageWriteException;
+
+public class BinaryFileFunctions implements BinaryConstants
+{
+ protected boolean debug = false;
+
+ public final void setDebug(boolean b)
+ {
+ debug = b;
+ }
+
+ public final boolean getDebug()
+ {
+ return debug;
+ }
+
+ protected final void readRandomBytes(InputStream is)
+ throws ImageReadException, IOException
+ {
+
+ for (int counter = 0; counter < 100; counter++)
+ {
+ readByte("" + counter, is, "Random Data");
+ }
+ }
+
+ public final void debugNumber(String msg, int data)
+ {
+ debugNumber(msg, data, 1);
+ }
+
+ public final void debugNumber(String msg, int data, int bytes)
+ {
+ debugNumber(new PrintWriter(new OutputStreamWriter(System.out)), msg,
+ data, bytes);
+ }
+
+ public final void debugNumber(PrintWriter pw, String msg, int data)
+ {
+ debugNumber(pw, msg, data, 1);
+ }
+
+ public final void debugNumber(PrintWriter pw, String msg, int data,
+ int bytes)
+ {
+ pw.print(msg + ": " + data + " (");
+ int byteData = data;
+ for (int i = 0; i < bytes; i++)
+ {
+ if (i > 0)
+ System.out.print(",");
+ int singleByte = 0xff & byteData;
+ pw.print((char) singleByte + " [" + singleByte + "]");
+ byteData >>= 8;
+ }
+ pw.println(") [0x" + Integer.toHexString(data) + ", "
+ + Integer.toBinaryString(data) + "]");
+ pw.flush();
+ }
+
+ public final boolean startsWith(byte haystack[], byte needle[])
+ {
+ if (needle == null)
+ return false;
+ if (haystack == null)
+ return false;
+ if (needle.length > haystack.length)
+ return false;
+
+ for (int i = 0; i < needle.length; i++)
+ {
+ if (needle[i] != haystack[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ public final void readAndVerifyBytes(InputStream is, 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, InputStream is,
+ byte expected[], String exception) throws ImageReadException,
+ IOException
+ {
+ byte bytes[] = readByteArray(name, expected.length, is, 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(InputStream is, 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(InputStream is, 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, InputStream is, String exception)
+ throws ImageReadException, 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, byteOrder);
+ int divisor = convertByteArrayToInt(name, bytes, start + 4, byteOrder);
+
+ return new RationalNumber(numerator, divisor);
+ }
+
+ protected final int convertByteArrayToInt(String name, byte bytes[],
+ int byteOrder)
+ {
+ return convertByteArrayToInt(name, bytes, 0, byteOrder);
+ }
+
+ protected final int convertByteArrayToInt(String name, byte bytes[],
+ int start, int byteOrder)
+ {
+ byte byte0 = bytes[start + 0];
+ byte byte1 = bytes[start + 1];
+ byte byte2 = bytes[start + 2];
+ byte byte3 = bytes[start + 3];
+
+ int result;
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ result = ((0xff & byte0) << 24) | ((0xff & byte1) << 16)
+ | ((0xff & byte2) << 8) | ((0xff & byte3) << 0);
+ }
+ else
+ {
+ // intel, little endian
+ result = ((0xff & byte3) << 24) | ((0xff & byte2) << 16)
+ | ((0xff & byte1) << 8) | ((0xff & 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,
+ byteOrder);
+ }
+
+ return result;
+ }
+
+ protected final void writeIntInToByteArray(int value, byte bytes[],
+ int start, int byteOrder)
+ {
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ bytes[start + 0] = (byte) (value >> 24);
+ bytes[start + 1] = (byte) (value >> 16);
+ bytes[start + 2] = (byte) (value >> 8);
+ bytes[start + 3] = (byte) (value >> 0);
+ }
+ else
+ {
+ bytes[start + 3] = (byte) (value >> 24);
+ bytes[start + 2] = (byte) (value >> 16);
+ bytes[start + 1] = (byte) (value >> 8);
+ bytes[start + 0] = (byte) (value >> 0);
+ }
+ }
+
+ protected final byte[] convertIntArrayToByteArray(int values[],
+ int byteOrder)
+ {
+ byte result[] = new byte[values.length * 4];
+
+ for (int i = 0; i < values.length; i++)
+ {
+ writeIntInToByteArray(values[i], result, i * 4, byteOrder);
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertShortArrayToByteArray(int values[],
+ int byteOrder)
+ {
+ byte result[] = new byte[values.length * 2];
+
+ for (int i = 0; i < values.length; i++)
+ {
+ int value = values[i];
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ result[i * 2 + 0] = (byte) (value >> 8);
+ result[i * 2 + 1] = (byte) (value >> 0);
+ }
+ else
+ {
+ result[i * 2 + 1] = (byte) (value >> 8);
+ result[i * 2 + 0] = (byte) (value >> 0);
+ }
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertShortToByteArray(int value, int byteOrder)
+ {
+ byte result[] = new byte[2];
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ result[0] = (byte) (value >> 8);
+ result[1] = (byte) (value >> 0);
+ }
+ else
+ {
+ result[1] = (byte) (value >> 8);
+ result[0] = (byte) (value >> 0);
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertIntArrayToRationalArray(int numerators[],
+ int denominators[], int byteOrder) throws ImageWriteException
+ {
+ if (numerators.length != denominators.length)
+ throw new ImageWriteException("numerators.length ("
+ + numerators.length + " != denominators.length ("
+ + denominators.length + ")");
+
+ byte result[] = new byte[numerators.length * 8];
+
+ for (int i = 0; i < numerators.length; i++)
+ {
+ writeIntInToByteArray(numerators[i], result, i * 8, byteOrder);
+ writeIntInToByteArray(denominators[i], result, i * 8 + 4, byteOrder);
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertRationalArrayToByteArray(
+ RationalNumber numbers[], int byteOrder) throws ImageWriteException
+ {
+ // Debug.debug("convertRationalArrayToByteArray 2");
+ byte result[] = new byte[numbers.length * 8];
+
+ for (int i = 0; i < numbers.length; i++)
+ {
+ writeIntInToByteArray(numbers[i].numerator, result, i * 8,
+ byteOrder);
+ writeIntInToByteArray(numbers[i].divisor, result, i * 8 + 4,
+ byteOrder);
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertRationalToByteArray(RationalNumber number,
+ int byteOrder) throws ImageWriteException
+ {
+ byte result[] = new byte[8];
+
+ writeIntInToByteArray(number.numerator, result, 0, byteOrder);
+ writeIntInToByteArray(number.divisor, result, 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);
+ }
+
+ return result;
+ }
+
+ public final byte[] readByteArray(String name, int length, InputStream is,
+ 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 < 50)); i++)
+ {
+ debugNumber(name + " (" + i + ")", 0xff & result[i]);
+ }
+ }
+ return result;
+ }
+
+ public final void debugByteArray(String name, byte bytes[])
+ {
+ System.out.println(name + ": " + bytes.length);
+
+ for (int i = 0; ((i < bytes.length) && (i < 50)); i++)
+ {
+ debugNumber("\t" + " (" + i + ")", 0xff & 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;
+ }
+
+ 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[], byte b[])
+ {
+ if (a.length != b.length)
+ {
+ System.out.println("length mismatch: " + a.length + " != "
+ + b.length);
+ return false;
+ }
+
+ return compareByteArrays(a, 0, b, 0, a.length);
+ }
+
+ 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("\t" + "a[" + (aStart + i) + "]", a[aStart + i]);
+ debugNumber("\t" + "b[" + (bStart + i) + "]", b[bStart + i]);
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected final int read4Bytes(String name, InputStream is,
+ String exception, int byteOrder) throws ImageReadException,
+ 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, InputStream is,
+ String exception, int byteOrder) throws ImageReadException,
+ IOException
+ {
+ byte byte0 = (byte) is.read();
+ byte byte1 = (byte) is.read();
+ byte byte2 = (byte) is.read();
+
+ int result;
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ result = ((0xff & byte0) << 16) | ((0xff & byte1) << 8)
+ | ((0xff & byte2) << 0);
+ else
+ // intel, little endian
+ result = ((0xff & byte2) << 16) | ((0xff & byte1) << 8)
+ | ((0xff & byte0) << 0);
+
+ if (debug)
+ debugNumber(name, result, 3);
+
+ return result;
+ //
+ //
+ // 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, InputStream is,
+ String exception, int byteOrder) throws ImageReadException,
+ 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);
+ }
+
+ 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 printCharQuad(PrintWriter pw, String msg, int i)
+ {
+ pw.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));
+ }
+
+ public 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
+ {
+ if (debug)
+ {
+ System.out.println("getRAFBytes pos" + ": " + pos);
+ System.out.println("getRAFBytes length" + ": " + length);
+ }
+
+ byte result[] = new byte[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 final float convertByteArrayToFloat(String name, byte bytes[],
+ int byteOrder)
+ {
+ return convertByteArrayToFloat(name, bytes, 0, byteOrder);
+ }
+
+ protected final float convertByteArrayToFloat(String name, byte bytes[],
+ int start, int byteOrder)
+ {
+ // TODO: not tested; probably wrong.
+
+ byte byte0 = bytes[start + 0];
+ byte byte1 = bytes[start + 1];
+ byte byte2 = bytes[start + 2];
+ byte byte3 = bytes[start + 3];
+
+ int bits;
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ bits = ((0xff & byte0) << 24) | ((0xff & byte1) << 16)
+ | ((0xff & byte2) << 8) | ((0xff & byte3) << 0);
+ }
+ else
+ {
+ // intel, little endian
+ bits = ((0xff & byte3) << 24) | ((0xff & byte2) << 16)
+ | ((0xff & byte1) << 8) | ((0xff & byte0) << 0);
+ }
+
+ float result = Float.intBitsToFloat(bits);
+
+ // if (debug)
+ // debugNumber(name, result, 4);
+
+ return result;
+ }
+
+ protected final float[] convertByteArrayToFloatArray(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;
+ }
+
+ float result[] = new float[length];
+
+ for (int i = 0; i < length; i++)
+ {
+ result[i] = convertByteArrayToFloat(name, bytes, start + i * 4,
+ byteOrder);
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertFloatToByteArray(float value, int byteOrder)
+ {
+ // TODO: not tested; probably wrong.
+ byte result[] = new byte[4];
+
+ int bits = Float.floatToRawIntBits(value);
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ result[0] = (byte) (0xff & (bits >> 0));
+ result[1] = (byte) (0xff & (bits >> 8));
+ result[2] = (byte) (0xff & (bits >> 16));
+ result[3] = (byte) (0xff & (bits >> 24));
+ }
+ else
+ {
+ result[3] = (byte) (0xff & (bits >> 0));
+ result[2] = (byte) (0xff & (bits >> 8));
+ result[1] = (byte) (0xff & (bits >> 16));
+ result[0] = (byte) (0xff & (bits >> 24));
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertFloatArrayToByteArray(float values[],
+ int byteOrder)
+ {
+ // TODO: not tested; probably wrong.
+ byte result[] = new byte[values.length * 4];
+ for (int i = 0; i < values.length; i++)
+ {
+ float value = values[i];
+ int bits = Float.floatToRawIntBits(value);
+
+ int start = i * 4;
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ result[start + 0] = (byte) (0xff & (bits >> 0));
+ result[start + 1] = (byte) (0xff & (bits >> 8));
+ result[start + 2] = (byte) (0xff & (bits >> 16));
+ result[start + 3] = (byte) (0xff & (bits >> 24));
+ }
+ else
+ {
+ result[start + 3] = (byte) (0xff & (bits >> 0));
+ result[start + 2] = (byte) (0xff & (bits >> 8));
+ result[start + 1] = (byte) (0xff & (bits >> 16));
+ result[start + 0] = (byte) (0xff & (bits >> 24));
+ }
+ }
+ return result;
+ }
+
+ protected final byte[] convertDoubleToByteArray(double value, int byteOrder)
+ {
+ // TODO: not tested; probably wrong.
+ byte result[] = new byte[8];
+
+ long bits = Double.doubleToRawLongBits(value);
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ result[0] = (byte) (0xff & (bits >> 0));
+ result[1] = (byte) (0xff & (bits >> 8));
+ result[2] = (byte) (0xff & (bits >> 16));
+ result[3] = (byte) (0xff & (bits >> 24));
+ result[4] = (byte) (0xff & (bits >> 32));
+ result[5] = (byte) (0xff & (bits >> 40));
+ result[6] = (byte) (0xff & (bits >> 48));
+ result[7] = (byte) (0xff & (bits >> 56));
+ }
+ else
+ {
+ result[7] = (byte) (0xff & (bits >> 0));
+ result[6] = (byte) (0xff & (bits >> 8));
+ result[5] = (byte) (0xff & (bits >> 16));
+ result[4] = (byte) (0xff & (bits >> 24));
+ result[3] = (byte) (0xff & (bits >> 32));
+ result[2] = (byte) (0xff & (bits >> 40));
+ result[1] = (byte) (0xff & (bits >> 48));
+ result[0] = (byte) (0xff & (bits >> 56));
+ }
+
+ return result;
+ }
+
+ protected final byte[] convertDoubleArrayToByteArray(double values[],
+ int byteOrder)
+ {
+ // TODO: not tested; probably wrong.
+ byte result[] = new byte[values.length * 8];
+ for (int i = 0; i < values.length; i++)
+ {
+ double value = values[i];
+ long bits = Double.doubleToRawLongBits(value);
+
+ int start = i * 8;
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ result[start + 0] = (byte) (0xff & (bits >> 0));
+ result[start + 1] = (byte) (0xff & (bits >> 8));
+ result[start + 2] = (byte) (0xff & (bits >> 16));
+ result[start + 3] = (byte) (0xff & (bits >> 24));
+ result[start + 4] = (byte) (0xff & (bits >> 32));
+ result[start + 5] = (byte) (0xff & (bits >> 40));
+ result[start + 6] = (byte) (0xff & (bits >> 48));
+ result[start + 7] = (byte) (0xff & (bits >> 56));
+ }
+ else
+ {
+ result[start + 7] = (byte) (0xff & (bits >> 0));
+ result[start + 6] = (byte) (0xff & (bits >> 8));
+ result[start + 5] = (byte) (0xff & (bits >> 16));
+ result[start + 4] = (byte) (0xff & (bits >> 24));
+ result[start + 3] = (byte) (0xff & (bits >> 32));
+ result[start + 2] = (byte) (0xff & (bits >> 40));
+ result[start + 1] = (byte) (0xff & (bits >> 48));
+ result[start + 0] = (byte) (0xff & (bits >> 56));
+ }
+ }
+ return result;
+ }
+
+ protected final double convertByteArrayToDouble(String name, byte bytes[],
+ int byteOrder)
+ {
+ return convertByteArrayToDouble(name, bytes, 0, byteOrder);
+ }
+
+ protected final double convertByteArrayToDouble(String name, byte bytes[],
+ int start, int byteOrder)
+ {
+ // TODO: not tested; probably wrong.
+
+ byte byte0 = bytes[start + 0];
+ byte byte1 = bytes[start + 1];
+ byte byte2 = bytes[start + 2];
+ byte byte3 = bytes[start + 3];
+ byte byte4 = bytes[start + 4];
+ byte byte5 = bytes[start + 5];
+ byte byte6 = bytes[start + 6];
+ byte byte7 = bytes[start + 7];
+
+ long bits;
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ {
+ bits = ((0xff & byte0) << 56) | ((0xff & byte1) << 48)
+ | ((0xff & byte2) << 40) | ((0xff & byte3) << 32)
+ | ((0xff & byte4) << 24) | ((0xff & byte5) << 16)
+ | ((0xff & byte6) << 8) | ((0xff & byte7) << 0);
+
+ }
+ else
+ {
+ // intel, little endian
+ bits = ((0xff & byte7) << 56) | ((0xff & byte6) << 48)
+ | ((0xff & byte5) << 40) | ((0xff & byte4) << 32)
+ | ((0xff & byte3) << 24) | ((0xff & byte2) << 16)
+ | ((0xff & byte1) << 8) | ((0xff & byte0) << 0);
+ }
+
+ double result = Double.longBitsToDouble(bits);
+
+ // if (debug)
+ // debugNumber(name, result, 4);
+
+ return result;
+
+ // byte array[];
+ // if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ // // ?? dunno byte order very likely wrong here.
+ // array = new byte[]{
+ // bytes[start + 0], bytes[start + 1], bytes[start + 2],
+ // bytes[start + 3], bytes[start + 4], bytes[start + 5],
+ // bytes[start + 6], bytes[start + 7],
+ //
+ // };
+ // else
+ // // ?? dunno byte order very likely wrong here.
+ // array = new byte[]{
+ // bytes[start + 3], bytes[start + 2], bytes[start + 1],
+ // bytes[start + 0], bytes[start + 7], bytes[start + 6],
+ // bytes[start + 5], bytes[start + 4],
+ // };
+ //
+ // double result = Double.NaN;
+ //
+ // try
+ // {
+ // ByteArrayInputStream bais = new ByteArrayInputStream(array);
+ // if (start > 0)
+ // {
+ // skipBytes(bais, start);
+ // // bais.skip(start);
+ // }
+ // DataInputStream dis = new DataInputStream(bais);
+ // result = dis.readDouble();
+ //
+ // dis.close();
+ // }
+ // catch (Exception e)
+ // {
+ // Debug.debug(e);
+ // }
+ //
+ // return result;
+ }
+
+ protected final double[] convertByteArrayToDoubleArray(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;
+ }
+
+ double result[] = new double[length];
+
+ for (int i = 0; i < length; i++)
+ {
+ result[i] = convertByteArrayToDouble(name, bytes, start + i * 8,
+ byteOrder);
+ }
+
+ return result;
+ }
+
+ protected void skipBytes(InputStream is, int length) throws IOException
+ {
+ this.skipBytes(is, length, "Couldn't skip bytes");
+ }
+
+ public final void copyStreamToStream(InputStream is, OutputStream os)
+ throws IOException
+ {
+ byte buffer[] = new byte[1024];
+ int read;
+ while ((read = is.read(buffer)) > 0)
+ {
+ os.write(buffer, 0, read);
+ }
+ }
+
+ public final byte[] getStreamBytes(InputStream is) throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ copyStreamToStream(is, os);
+ return os.toByteArray();
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileFunctions.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileParser.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileParser.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileParser.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,100 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.cmc.sanselan.ImageReadException;
+
+public class BinaryFileParser extends BinaryFileFunctions
+{
+ public BinaryFileParser(int byteOrder)
+ {
+ this.byteOrder = byteOrder;
+ }
+
+ public BinaryFileParser()
+ {
+
+ }
+
+ // default byte order for Java, many file formats.
+ private int byteOrder = BYTE_ORDER_NETWORK;
+
+ // protected boolean BYTE_ORDER_reversed = true;
+
+ protected void setByteOrder(int a, int b) throws ImageReadException,
+ IOException
+ {
+ 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;
+ }
+
+ 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, InputStream is, String exception)
+ throws ImageReadException, IOException
+ {
+ return read4Bytes(name, is, exception, byteOrder);
+ }
+
+ public final int read3Bytes(String name, InputStream is, String exception)
+ throws ImageReadException, IOException
+ {
+ return read3Bytes(name, is, exception, byteOrder);
+ }
+
+ public final int read2Bytes(String name, InputStream is, String exception)
+ throws ImageReadException, IOException
+ {
+ return read2Bytes(name, is, exception, byteOrder);
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryFileParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryInputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryInputStream.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryInputStream.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryInputStream.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,608 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+
+import org.cmc.sanselan.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(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,
+ IOException
+ {
+ 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;
+ }
+
+ 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 ImageReadException, IOException
+ {
+ return read4Bytes(name, exception, byteOrder);
+ }
+
+ public final int read3Bytes(String name, String exception)
+ throws ImageReadException, IOException
+ {
+ return read3Bytes(name, exception, byteOrder);
+ }
+
+ public final int read2Bytes(String name, String exception)
+ throws ImageReadException, IOException
+ {
+ return read2Bytes(name, exception, byteOrder);
+ }
+
+ protected final void readRandomBytes() throws ImageReadException,
+ 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 ImageReadException, 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;
+ }
+
+ 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 ImageReadException, 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 ImageReadException, 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 ImageReadException, 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);
+ }
+
+ 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");
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryOutputStream.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryOutputStream.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryOutputStream.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,138 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.cmc.sanselan.ImageWriteException;
+
+public class BinaryOutputStream extends OutputStream implements BinaryConstants
+{
+ protected boolean debug = false;
+
+ public final void setDebug(boolean b)
+ {
+ debug = b;
+ }
+
+ public final boolean getDebug()
+ {
+ return debug;
+ }
+
+ private final OutputStream os;
+
+ public BinaryOutputStream(OutputStream os, int byteOrder)
+ {
+ this.byteOrder = byteOrder;
+ this.os = os;
+ }
+
+ public BinaryOutputStream(OutputStream os)
+ {
+ this.os = os;
+ }
+
+ // default byte order for Java, many file formats.
+ private int byteOrder = BYTE_ORDER_NETWORK;
+
+ protected void setByteOrder(int a, int b) throws ImageWriteException,
+ IOException
+ {
+ if (a != b)
+ throw new ImageWriteException("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 ImageWriteException("Unknown Byte Order hint: " + a);
+ }
+
+ protected void setByteOrder(int byteOrder)
+ {
+ this.byteOrder = byteOrder;
+ }
+
+ protected int getByteOrder()
+ {
+ return byteOrder;
+ }
+
+ public void write(int i) throws IOException
+ {
+ // os.write(0xff & i); // unnecessary
+ os.write(i);
+ }
+
+ public final void write4Bytes(int value) throws ImageWriteException,
+ IOException
+ {
+ writeNBytes(value, 4);
+ }
+
+ public final void write3Bytes(int value) throws ImageWriteException,
+ IOException
+ {
+ writeNBytes(value, 3);
+ }
+
+ public final void write2Bytes(int value) throws ImageWriteException,
+ IOException
+ {
+ writeNBytes(value, 2);
+ }
+
+ public final void writeByteArray(byte bytes[]) throws IOException
+ {
+ os.write(bytes, 0, bytes.length);
+ }
+
+ private byte[] convertValueToByteArray(int value, int n)
+ {
+ byte result[] = new byte[n];
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ int b = 0xff & (value >> (8 * (n - i - 1)));
+ result[i] = (byte) b;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < n; i++)
+ {
+ int b = 0xff & (value >> (8 * i));
+ result[i] = (byte) b;
+ }
+ }
+
+ return result;
+ }
+
+ private final void writeNBytes(int value, int n)
+ throws ImageWriteException, IOException
+ {
+ write(convertValueToByteArray(value, n));
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BinaryOutputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStream.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStream.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStream.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,123 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BitInputStream extends InputStream implements BinaryConstants
+{
+ // TODO should be byte order conscious, ie TIFF for reading
+ // samples size<8 - shuoldn't that effect their order within byte?
+ private final InputStream is;
+
+ public BitInputStream(InputStream is)
+ {
+ this.is = is;
+ // super(is);
+ }
+
+ public int read() throws IOException
+ {
+ if (cacheBitsRemaining > 0)
+ throw new IOException("BitInputStream: incomplete bit read");
+ return is.read();
+ }
+
+ private int cache;
+ private int cacheBitsRemaining = 0;
+ private long bytes_read = 0;
+
+ public final int readBits(int count) throws IOException
+ {
+ if (count < 8)
+ {
+ if (cacheBitsRemaining == 0)
+ {
+ // fill cache
+ cache = is.read();
+ cacheBitsRemaining = 8;
+ bytes_read++;
+ }
+ if (count > cacheBitsRemaining)
+ throw new IOException(
+ "BitInputStream: can't read bit fields across bytes");
+
+ // int bits_to_shift = cache_bits_remaining - count;
+ cacheBitsRemaining -= count;
+ int bits = cache >> cacheBitsRemaining;
+
+ switch (count)
+ {
+ case 1 :
+ return bits & 1;
+ case 2 :
+ return bits & 3;
+ case 3 :
+ return bits & 7;
+ case 4 :
+ return bits & 15;
+ case 5 :
+ return bits & 31;
+ case 6 :
+ return bits & 63;
+ case 7 :
+ return bits & 127;
+ }
+
+ }
+ if (cacheBitsRemaining > 0)
+ throw new IOException("BitInputStream: incomplete bit read");
+
+ if (count == 8)
+ {
+ bytes_read++;
+ return is.read();
+ }
+
+ if (count == 16)
+ {
+ bytes_read += 2;
+ return (is.read() << 8) | (is.read() << 0);
+ }
+
+ if (count == 24)
+ {
+ bytes_read += 3;
+ return (is.read() << 16) | (is.read() << 8) | (is.read() << 0);
+ }
+
+ if (count == 32)
+ {
+ bytes_read += 4;
+ return (is.read() << 24) | (is.read() << 16) | (is.read() << 8)
+ | (is.read() << 0);
+ }
+
+ throw new IOException("BitInputStream: unknown error");
+ }
+
+ public void flushCache()
+ {
+ cacheBitsRemaining = 0;
+ }
+
+ public long getBytesRead()
+ {
+ return bytes_read;
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStreamFlexible.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStreamFlexible.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStreamFlexible.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStreamFlexible.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,115 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BitInputStreamFlexible extends InputStream
+ implements
+ BinaryConstants
+{
+ // TODO should be byte order conscious, ie TIFF for reading
+ // samples size<8 - shuoldn't that effect their order within byte?
+ private final InputStream is;
+
+ public BitInputStreamFlexible(InputStream is)
+ {
+ this.is = is;
+ // super(is);
+ }
+
+ public int read() throws IOException
+ {
+ if (cacheBitsRemaining > 0)
+ throw new IOException("BitInputStream: incomplete bit read");
+ return is.read();
+ }
+
+ private int cache;
+ private int cacheBitsRemaining = 0;
+ private long bytesRead = 0;
+
+ public final int readBits(int count) throws IOException
+ {
+
+ if (count <= 32) // catch-all
+ {
+ int result = 0;
+ // int done = 0;
+
+ if (cacheBitsRemaining > 0)
+ {
+ if (count >= cacheBitsRemaining)
+ {
+ result = ((1 << cacheBitsRemaining) - 1) & cache;
+ count -= cacheBitsRemaining;
+ cacheBitsRemaining = 0;
+ }
+ else
+ {
+ // cache >>= count;
+ cacheBitsRemaining -= count;
+ result = ((1 << count) - 1)
+ & (cache >> cacheBitsRemaining);
+ count = 0;
+ }
+ }
+ while (count >= 8)
+ {
+ cache = is.read();
+ if (cache < 0)
+ throw new IOException("couldn't read bits");
+ System.out.println("cache 1: " + cache + " ("
+ + Integer.toHexString(cache) + ", "
+ + Integer.toBinaryString(cache) + ")");
+ bytesRead++;
+ result = (result << 8) | (0xff & cache);
+ count -= 8;
+ }
+ if (count > 0)
+ {
+ cache = is.read();
+ if (cache < 0)
+ throw new IOException("couldn't read bits");
+ System.out.println("cache 2: " + cache + " ("
+ + Integer.toHexString(cache) + ", "
+ + Integer.toBinaryString(cache) + ")");
+ bytesRead++;
+ cacheBitsRemaining = 8 - count;
+ result = (result << count)
+ | (((1 << count) - 1) & (cache >> cacheBitsRemaining));
+ count = 0;
+ }
+
+ return result;
+ }
+
+ throw new IOException("BitInputStream: unknown error");
+
+ }
+
+ public void flushCache()
+ {
+ cacheBitsRemaining = 0;
+ }
+
+ public long getBytesRead()
+ {
+ return bytesRead;
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/BitInputStreamFlexible.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/Compression.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/Compression.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/Compression.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/Compression.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,61 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.cmc.sanselan.ImageReadException;
+import org.cmc.sanselan.common.mylzw.MyLZWCompressor;
+import org.cmc.sanselan.common.mylzw.MyLZWDecompressor;
+
+public class Compression
+{
+
+ public byte[] decompressLZW(byte compressed[], int LZWMinimumCodeSize,
+ int expectedSize, int byteOrder) throws IOException
+ {
+ InputStream is = new ByteArrayInputStream(compressed);
+
+ MyLZWDecompressor decompressor = new MyLZWDecompressor(
+ LZWMinimumCodeSize, byteOrder);
+ byte[] result = decompressor.decompress(is, expectedSize);
+
+ return result;
+ }
+
+ public byte[] decompressPackBits(byte compressed[], int expectedSize,
+ int byteOrder) throws ImageReadException, IOException
+ {
+ byte unpacked[] = new PackBits().decompress(compressed, expectedSize);
+ return unpacked;
+ }
+
+ public byte[] compressLZW(byte src[], int LZWMinimumCodeSize,
+ int byteOrder, boolean earlyLimit) throws IOException
+
+ {
+ MyLZWCompressor compressor = new MyLZWCompressor(LZWMinimumCodeSize,
+ byteOrder, earlyLimit);
+
+ byte compressed[] = compressor.compress(src);
+
+ return compressed;
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/Compression.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IBufferedImageFactory.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IBufferedImageFactory.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IBufferedImageFactory.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IBufferedImageFactory.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,10 @@
+package org.cmc.sanselan.common;
+
+import java.awt.image.BufferedImage;
+
+public interface IBufferedImageFactory
+{
+ public BufferedImage getColorBufferedImage(int width, int height);
+
+ public BufferedImage getGrayscaleBufferedImage(int width, int height);
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IBufferedImageFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IImageMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IImageMetadata.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IImageMetadata.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IImageMetadata.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,33 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.util.Vector;
+
+public interface IImageMetadata
+{
+ public String toString(String prefix);
+
+ public Vector getItems();
+
+ public interface IImageMetadataItem
+ {
+ public String toString(String prefix);
+
+ public String toString();
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/IImageMetadata.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ImageMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ImageMetadata.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ImageMetadata.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ImageMetadata.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,107 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.util.Vector;
+
+public class ImageMetadata implements IImageMetadata
+{
+
+ private final Vector items = new Vector();
+
+ public void add(String keyword, String text)
+ {
+ add(new Item(keyword, text));
+ }
+
+ public void add(IImageMetadataItem item)
+ {
+ items.add(item);
+ }
+
+ public Vector getItems()
+ {
+ return new Vector(items);
+ }
+
+ protected static final String newline = System
+ .getProperty("line.separator");
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ if (null == prefix)
+ prefix = "";
+
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < items.size(); i++)
+ {
+ if (i > 0)
+ result.append(newline);
+ // if (null != prefix)
+ // result.append(prefix);
+
+ ImageMetadata.IImageMetadataItem item = (ImageMetadata.IImageMetadataItem) items
+ .get(i);
+ result.append(item.toString(prefix + "\t"));
+
+ // Debug.debug("prefix", prefix);
+ // Debug.debug("item", items.get(i));
+ // Debug.debug();
+ }
+ return result.toString();
+ }
+
+ public static class Item implements IImageMetadataItem
+ {
+ private final String keyword, text;
+
+ public Item(String keyword, String text)
+ {
+ this.keyword = keyword;
+ this.text = text;
+ }
+
+ public String getKeyword()
+ {
+ return keyword;
+ }
+
+ public String getText()
+ {
+ return text;
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ String result = keyword + ": " + text;
+ if (null != prefix)
+ result = prefix + result;
+ return result;
+ }
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ImageMetadata.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/MyByteArrayOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/MyByteArrayOutputStream.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/MyByteArrayOutputStream.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/MyByteArrayOutputStream.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,59 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class MyByteArrayOutputStream extends OutputStream
+// some performace benefit, because not thread safe.
+{
+ private final byte bytes[];
+
+ public MyByteArrayOutputStream(int length)
+ {
+ bytes = new byte[length];
+ }
+
+ private int count = 0;
+
+ public void write(int value) throws IOException
+ {
+ if (count >= bytes.length)
+ throw new IOException("Write exceeded expected length (" + count
+ + ", " + bytes.length + ")");
+
+ bytes[count] = (byte) value;
+ count++;
+ }
+
+ public byte[] toByteArray()
+ {
+ if (count < bytes.length)
+ {
+ byte result[] = new byte[count];
+ System.arraycopy(bytes, 0, result, 0, count);
+ return result;
+ }
+ return bytes;
+ }
+
+ public int getBytesWritten()
+ {
+ return count;
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/MyByteArrayOutputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/PackBits.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/PackBits.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/PackBits.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/PackBits.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,170 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.cmc.sanselan.ImageReadException;
+
+public class PackBits
+{
+
+ public byte[] decompress(byte bytes[], int expected)
+ throws ImageReadException, IOException
+ {
+ int total = 0;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // Loop until you get the number of unpacked bytes you are expecting:
+ int i = 0;
+ while (total < expected)
+
+ {
+ // Read the next source byte into n.
+ if (i >= bytes.length)
+ throw new ImageReadException(
+ "Tiff: Unpack bits source exhausted: " + i
+ + ", done + " + total + ", expected + "
+ + expected);
+
+ int n = bytes[i++];
+ // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
+ if ((n >= 0) && (n <= 127))
+ {
+
+ int count = n + 1;
+
+ total += count;
+ for (int j = 0; j < count; j++)
+ baos.write(bytes[i++]);
+ }
+ // Else if n is between -127 and -1 inclusive, copy the next byte -n+1
+ // times.
+ else if ((n >= -127) && (n <= -1))
+ {
+ int b = bytes[i++];
+ int count = -n + 1;
+
+ total += count;
+ for (int j = 0; j < count; j++)
+ baos.write(b);
+ }
+ else if (n == -128)
+ throw new ImageReadException("Packbits: " + n);
+ // Else if n is between -127 and -1 inclusive, copy the next byte -n+1
+ // times.
+ // else
+ // Else if n is -128, noop.
+ }
+ byte result[] = baos.toByteArray();
+
+ return result;
+
+ }
+
+ private int findNextDuplicate(byte bytes[], int start)
+ {
+ // int last = -1;
+ if (start >= bytes.length)
+ return -1;
+
+ byte prev = bytes[start];
+
+ for (int i = start + 1; i < bytes.length; i++)
+ {
+ byte b = bytes[i];
+
+ if (b == prev)
+ return i - 1;
+
+ prev = b;
+ }
+
+ return -1;
+ }
+
+ private int findRunLength(byte bytes[], int start)
+ {
+ byte b = bytes[start];
+
+ int i;
+
+ for (i = start + 1; (i < bytes.length) && (bytes[i] == b); i++)
+ ;
+
+ return i - start;
+ }
+
+ public byte[] compress(byte bytes[]) throws IOException
+ {
+ MyByteArrayOutputStream baos = new MyByteArrayOutputStream(
+ bytes.length * 2); // max length 1 extra byte for every 128
+
+ int ptr = 0;
+ int count = 0;
+ while (ptr < bytes.length)
+ {
+ count++;
+ int dup = findNextDuplicate(bytes, ptr);
+
+ if (dup == ptr) // write run length
+ {
+ int len = findRunLength(bytes, dup);
+ int actual_len = Math.min(len, 128);
+ baos.write(-(actual_len - 1));
+ baos.write(bytes[ptr]);
+ ptr += actual_len;
+ }
+ else
+ { // write literals
+ int len = dup - ptr;
+
+ if (dup > 0)
+ {
+ int runlen = findRunLength(bytes, dup);
+ if (runlen < 3) // may want to discard next run.
+ {
+ int nextptr = ptr + len + runlen;
+ int nextdup = findNextDuplicate(bytes, nextptr);
+ if (nextdup != nextptr) // discard 2-byte run
+ {
+ dup = nextdup;
+ len = dup - ptr;
+ }
+ }
+ }
+
+ if (dup < 0)
+ len = bytes.length - ptr;
+ int actual_len = Math.min(len, 128);
+
+ baos.write(actual_len - 1);
+ for (int i = 0; i < actual_len; i++)
+ {
+ baos.write(bytes[ptr]);
+ ptr++;
+ }
+ }
+ }
+ byte result[] = baos.toByteArray();
+
+ return result;
+
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/PackBits.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/RationalNumber.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/RationalNumber.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/RationalNumber.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/RationalNumber.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,71 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.text.NumberFormat;
+
+public class RationalNumber extends Number
+
+{
+ public final int numerator;
+ public final int divisor;
+
+ public RationalNumber(int numerator, int divisor)
+ {
+ this.numerator = numerator;
+ this.divisor = divisor;
+ }
+
+ public double doubleValue()
+ {
+ return (double) numerator / (double) divisor;
+ }
+
+ public float floatValue()
+ {
+ return (float) numerator / (float) divisor;
+ }
+
+ public int intValue()
+ {
+ return (int) numerator / (int) divisor;
+ }
+
+ public long longValue()
+ {
+ return (long) numerator / (long) divisor;
+ }
+
+ public String toString()
+ {
+ if (divisor == 0)
+ return "Invalid rational number; Numerator: " + numerator
+ + ", Divisor: " + divisor;
+ if ((numerator % divisor) == 0)
+ return "" + (numerator / divisor);
+ return numerator + "/" + divisor;
+ }
+
+ public String toDisplayString()
+ {
+ if ((numerator % divisor) == 0)
+ return "" + (numerator / divisor);
+ NumberFormat nf = NumberFormat.getNumberInstance();
+ nf.setMaximumFractionDigits(3);
+ return nf.format((double) numerator / (double) divisor);
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/RationalNumber.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/SimpleBufferedImageFactory.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/SimpleBufferedImageFactory.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/SimpleBufferedImageFactory.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/SimpleBufferedImageFactory.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,16 @@
+package org.cmc.sanselan.common;
+
+import java.awt.image.BufferedImage;
+
+public class SimpleBufferedImageFactory implements IBufferedImageFactory
+{
+ public BufferedImage getColorBufferedImage(int width, int height)
+ {
+ return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ public BufferedImage getGrayscaleBufferedImage(int width, int height)
+ {
+ return new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
+ }
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/SimpleBufferedImageFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ZLibInflater.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ZLibInflater.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ZLibInflater.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ZLibInflater.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,36 @@
+/*
+ * 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.cmc.sanselan.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.zip.InflaterInputStream;
+
+import org.cmc.sanselan.ImageReadException;
+
+public class ZLibInflater extends BinaryFileFunctions
+{
+ public final byte[] zlibInflate(byte bytes[]) throws ImageReadException,
+ IOException
+ // slow, probably.
+ {
+ ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+ InflaterInputStream zIn = new InflaterInputStream(in);
+ return getStreamBytes(zIn);
+ }
+
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/ZLibInflater.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSource.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSource.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSource.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSource.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,61 @@
+/*
+ * 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.cmc.sanselan.common.byteSources;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.cmc.sanselan.common.BinaryFileFunctions;
+
+public abstract class ByteSource extends BinaryFileFunctions
+{
+ protected final String filename;
+
+ public ByteSource(final String filename)
+ {
+ this.filename = filename;
+ }
+
+ public final InputStream getInputStream(int start) throws IOException
+ {
+ InputStream is = getInputStream();
+
+ skipBytes(is, start);
+
+ return is;
+ }
+
+ public abstract InputStream getInputStream() throws IOException;
+
+ public abstract byte[] getBlock(int start, int length) throws IOException;
+
+ public abstract byte[] getAll() throws IOException;
+
+// public abstract long getLength();
+//
+// public byte[] getAll() throws IOException
+// {
+// return getBlock(0, (int) getLength());
+// }
+
+ public abstract String getDescription();
+
+ public final String getFilename()
+ {
+ return filename;
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceArray.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceArray.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceArray.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceArray.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,70 @@
+/*
+ * 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.cmc.sanselan.common.byteSources;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ByteSourceArray extends ByteSource
+{
+ private final byte bytes[];
+
+ public ByteSourceArray(String filename, byte bytes[])
+ {
+ super(filename);
+ this.bytes = bytes;
+ }
+
+ public ByteSourceArray(byte bytes[])
+ {
+ super(null);
+ this.bytes = bytes;
+ }
+
+ public InputStream getInputStream() //throws IOException
+ {
+ return new ByteArrayInputStream(bytes);
+ }
+
+ public byte[] getBlock(int start, int length) throws IOException
+ {
+ if (start + length > bytes.length)
+ throw new IOException("Could not read block.");
+
+ byte result[] = new byte[length];
+ System.arraycopy(bytes, start, result, 0, length);
+ return result;
+ }
+
+// public long getLength()
+// {
+// return bytes.length;
+// }
+
+ public byte[] getAll() throws IOException
+ {
+ return bytes;
+ }
+
+
+ public String getDescription()
+ {
+ return bytes.length + " byte array";
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceArray.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceFile.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceFile.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceFile.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceFile.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,116 @@
+/*
+ * 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.cmc.sanselan.common.byteSources;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+
+import org.cmc.sanselan.util.Debug;
+
+public class ByteSourceFile extends ByteSource
+{
+ private final File file;
+
+ public ByteSourceFile(File file)
+ {
+ super(file.getName());
+ this.file = file;
+ }
+
+ public InputStream getInputStream() throws IOException
+ {
+ FileInputStream is = null;
+ BufferedInputStream bis = null;
+ is = new FileInputStream(file);
+ bis = new BufferedInputStream(is);
+
+ return bis;
+ }
+
+ public byte[] getBlock(int start, int length) throws IOException
+ {
+ RandomAccessFile raf = null;
+ try
+ {
+ raf = new RandomAccessFile(file, "r");
+
+ return getRAFBytes(raf, start, length,
+ "Could not read value from file");
+ }
+ finally
+ {
+ try
+ {
+ raf.close();
+ }
+ catch (Exception e)
+ {
+ Debug.debug(e);
+ }
+
+ }
+ }
+
+// public long getLength()
+// {
+// // System.out.println("file.length(): " + file.length());
+//
+// return file.length();
+// }
+
+ public byte[] getAll() throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ InputStream is = null;
+ try
+ {
+ is = new FileInputStream(file);
+ is = new BufferedInputStream(is);
+ byte buffer[] = new byte[1024];
+ int read;
+ while ((read = is.read(buffer)) > 0)
+ {
+ baos.write(buffer, 0, read);
+ }
+ return baos.toByteArray();
+ }
+ finally
+ {
+ try
+ {
+ if (null != is)
+ is.close();
+ }
+ catch (IOException e)
+ {
+ // Debug.d
+ }
+ }
+ }
+
+ public String getDescription()
+ {
+ return "File: '" + file.getAbsolutePath() + "'";
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/common/byteSources/ByteSourceFile.java
------------------------------------------------------------------------------
svn:eol-style = native