| /* |
| * 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. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.xmlgraphics.image.codec.tiff; |
| |
| import java.io.Serializable; |
| |
| /** |
| * A class representing a field in a TIFF 6.0 Image File Directory. |
| * |
| * <p> The TIFF file format is described in more detail in the |
| * comments for the TIFFDescriptor class. |
| * |
| * <p> A field in a TIFF Image File Directory (IFD). A field is defined |
| * as a sequence of values of identical data type. TIFF 6.0 defines |
| * 12 data types, which are mapped internally onto the Java datatypes |
| * byte, int, long, float, and double. |
| * |
| * <p><b> This class is not a committed part of the JAI API. It may |
| * be removed or changed in future releases of JAI.</b> |
| * |
| * @see TIFFDirectory |
| */ |
| public class TIFFField extends Object implements Comparable, Serializable { |
| |
| /** Flag for 8 bit unsigned integers. */ |
| public static final int TIFF_BYTE = 1; |
| |
| /** Flag for null-terminated ASCII strings. */ |
| public static final int TIFF_ASCII = 2; |
| |
| /** Flag for 16 bit unsigned integers. */ |
| public static final int TIFF_SHORT = 3; |
| |
| /** Flag for 32 bit unsigned integers. */ |
| public static final int TIFF_LONG = 4; |
| |
| /** Flag for pairs of 32 bit unsigned integers. */ |
| public static final int TIFF_RATIONAL = 5; |
| |
| /** Flag for 8 bit signed integers. */ |
| public static final int TIFF_SBYTE = 6; |
| |
| /** Flag for 8 bit uninterpreted bytes. */ |
| public static final int TIFF_UNDEFINED = 7; |
| |
| /** Flag for 16 bit signed integers. */ |
| public static final int TIFF_SSHORT = 8; |
| |
| /** Flag for 32 bit signed integers. */ |
| public static final int TIFF_SLONG = 9; |
| |
| /** Flag for pairs of 32 bit signed integers. */ |
| public static final int TIFF_SRATIONAL = 10; |
| |
| /** Flag for 32 bit IEEE floats. */ |
| public static final int TIFF_FLOAT = 11; |
| |
| /** Flag for 64 bit IEEE doubles. */ |
| public static final int TIFF_DOUBLE = 12; |
| |
| /** The tag number. */ |
| int tag; |
| |
| /** The tag type. */ |
| int type; |
| |
| /** The number of data items present in the field. */ |
| int count; |
| |
| /** The field data. */ |
| Object data; |
| |
| /** The default constructor. */ |
| TIFFField() {} |
| |
| /** |
| * Constructs a TIFFField with arbitrary data. The data |
| * parameter must be an array of a Java type appropriate for the |
| * type of the TIFF field. Since there is no available 32-bit |
| * unsigned datatype, long is used. The mapping between types is |
| * as follows: |
| * |
| * <table border=1> |
| * <tr> |
| * <th> TIFF type </th> <th> Java type </th> |
| * <tr> |
| * <td><tt>TIFF_BYTE</tt></td> <td><tt>byte</tt></td> |
| * <tr> |
| * <td><tt>TIFF_ASCII</tt></td> <td><tt>String</tt></td> |
| * <tr> |
| * <td><tt>TIFF_SHORT</tt></td> <td><tt>char</tt></td> |
| * <tr> |
| * <td><tt>TIFF_LONG</tt></td> <td><tt>long</tt></td> |
| * <tr> |
| * <td><tt>TIFF_RATIONAL</tt></td> <td><tt>long[2]</tt></td> |
| * <tr> |
| * <td><tt>TIFF_SBYTE</tt></td> <td><tt>byte</tt></td> |
| * <tr> |
| * <td><tt>TIFF_UNDEFINED</tt></td> <td><tt>byte</tt></td> |
| * <tr> |
| * <td><tt>TIFF_SSHORT</tt></td> <td><tt>short</tt></td> |
| * <tr> |
| * <td><tt>TIFF_SLONG</tt></td> <td><tt>int</tt></td> |
| * <tr> |
| * <td><tt>TIFF_SRATIONAL</tt></td> <td><tt>int[2]</tt></td> |
| * <tr> |
| * <td><tt>TIFF_FLOAT</tt></td> <td><tt>float</tt></td> |
| * <tr> |
| * <td><tt>TIFF_DOUBLE</tt></td> <td><tt>double</tt></td> |
| * </table> |
| */ |
| public TIFFField(int tag, int type, int count, Object data) { |
| this.tag = tag; |
| this.type = type; |
| this.count = count; |
| this.data = data; |
| } |
| |
| /** |
| * Returns the tag number, between 0 and 65535. |
| */ |
| public int getTag() { |
| return tag; |
| } |
| |
| /** |
| * Returns the type of the data stored in the IFD. |
| * For a TIFF6.0 file, the value will equal one of the |
| * TIFF_ constants defined in this class. For future |
| * revisions of TIFF, higher values are possible. |
| * |
| */ |
| public int getType() { |
| return type; |
| } |
| |
| /** |
| * Returns the number of elements in the IFD. |
| */ |
| public int getCount() { |
| return count; |
| } |
| |
| /** |
| * Returns the data as an uninterpreted array of bytes. |
| * The type of the field must be one of TIFF_BYTE, TIFF_SBYTE, |
| * or TIFF_UNDEFINED; |
| * |
| * <p> For data in TIFF_BYTE format, the application must take |
| * care when promoting the data to longer integral types |
| * to avoid sign extension. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_BYTE, TIFF_SBYTE, or TIFF_UNDEFINED. |
| */ |
| public byte[] getAsBytes() { |
| return (byte[])data; |
| } |
| |
| /** |
| * Returns TIFF_SHORT data as an array of chars (unsigned 16-bit |
| * integers). |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_SHORT. |
| */ |
| public char[] getAsChars() { |
| return (char[])data; |
| } |
| |
| /** |
| * Returns TIFF_SSHORT data as an array of shorts (signed 16-bit |
| * integers). |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_SSHORT. |
| */ |
| public short[] getAsShorts() { |
| return (short[])data; |
| } |
| |
| /** |
| * Returns TIFF_SLONG data as an array of ints (signed 32-bit |
| * integers). |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_SLONG. |
| */ |
| public int[] getAsInts() { |
| return (int[])data; |
| } |
| |
| /** |
| * Returns TIFF_LONG data as an array of longs (signed 64-bit |
| * integers). |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_LONG. |
| */ |
| public long[] getAsLongs() { |
| return (long[])data; |
| } |
| |
| /** |
| * Returns TIFF_FLOAT data as an array of floats. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_FLOAT. |
| */ |
| public float[] getAsFloats() { |
| return (float[])data; |
| } |
| |
| /** |
| * Returns TIFF_DOUBLE data as an array of doubles. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_DOUBLE. |
| */ |
| public double[] getAsDoubles() { |
| return (double[])data; |
| } |
| |
| /** |
| * Returns TIFF_SRATIONAL data as an array of 2-element arrays of ints. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_SRATIONAL. |
| */ |
| public int[][] getAsSRationals() { |
| return (int[][])data; |
| } |
| |
| /** |
| * Returns TIFF_RATIONAL data as an array of 2-element arrays of longs. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_RATTIONAL. |
| */ |
| public long[][] getAsRationals() { |
| return (long[][])data; |
| } |
| |
| /** |
| * Returns data in TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT, |
| * TIFF_SSHORT, or TIFF_SLONG format as an int. |
| * |
| * <p> TIFF_BYTE and TIFF_UNDEFINED data are treated as unsigned; |
| * that is, no sign extension will take place and the returned |
| * value will be in the range [0, 255]. TIFF_SBYTE data will |
| * be returned in the range [-128, 127]. |
| * |
| * <p> A ClassCastException will be thrown if the field is not of |
| * type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT, |
| * TIFF_SSHORT, or TIFF_SLONG. |
| */ |
| public int getAsInt(int index) { |
| switch (type) { |
| case TIFF_BYTE: case TIFF_UNDEFINED: |
| return ((byte[])data)[index] & 0xff; |
| case TIFF_SBYTE: |
| return ((byte[])data)[index]; |
| case TIFF_SHORT: |
| return ((char[])data)[index] & 0xffff; |
| case TIFF_SSHORT: |
| return ((short[])data)[index]; |
| case TIFF_SLONG: |
| return ((int[])data)[index]; |
| default: |
| throw new ClassCastException(); |
| } |
| } |
| |
| /** |
| * Returns data in TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT, |
| * TIFF_SSHORT, TIFF_SLONG, or TIFF_LONG format as a long. |
| * |
| * <p> TIFF_BYTE and TIFF_UNDEFINED data are treated as unsigned; |
| * that is, no sign extension will take place and the returned |
| * value will be in the range [0, 255]. TIFF_SBYTE data will |
| * be returned in the range [-128, 127]. |
| * |
| * <p> A ClassCastException will be thrown if the field is not of |
| * type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT, |
| * TIFF_SSHORT, TIFF_SLONG, or TIFF_LONG. |
| */ |
| public long getAsLong(int index) { |
| switch (type) { |
| case TIFF_BYTE: case TIFF_UNDEFINED: |
| return ((byte[])data)[index] & 0xff; |
| case TIFF_SBYTE: |
| return ((byte[])data)[index]; |
| case TIFF_SHORT: |
| return ((char[])data)[index] & 0xffff; |
| case TIFF_SSHORT: |
| return ((short[])data)[index]; |
| case TIFF_SLONG: |
| return ((int[])data)[index]; |
| case TIFF_LONG: |
| return ((long[])data)[index]; |
| default: |
| throw new ClassCastException(); |
| } |
| } |
| |
| /** |
| * Returns data in any numerical format as a float. Data in |
| * TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated by |
| * dividing the numerator into the denominator using |
| * double-precision arithmetic and then truncating to single |
| * precision. Data in TIFF_SLONG, TIFF_LONG, or TIFF_DOUBLE |
| * format may suffer from truncation. |
| * |
| * <p> A ClassCastException will be thrown if the field is |
| * of type TIFF_UNDEFINED or TIFF_ASCII. |
| */ |
| public float getAsFloat(int index) { |
| switch (type) { |
| case TIFF_BYTE: |
| return ((byte[])data)[index] & 0xff; |
| case TIFF_SBYTE: |
| return ((byte[])data)[index]; |
| case TIFF_SHORT: |
| return ((char[])data)[index] & 0xffff; |
| case TIFF_SSHORT: |
| return ((short[])data)[index]; |
| case TIFF_SLONG: |
| return ((int[])data)[index]; |
| case TIFF_LONG: |
| return ((long[])data)[index]; |
| case TIFF_FLOAT: |
| return ((float[])data)[index]; |
| case TIFF_DOUBLE: |
| return (float)((double[])data)[index]; |
| case TIFF_SRATIONAL: |
| int[] ivalue = getAsSRational(index); |
| return (float)((double)ivalue[0]/ivalue[1]); |
| case TIFF_RATIONAL: |
| long[] lvalue = getAsRational(index); |
| return (float)((double)lvalue[0]/lvalue[1]); |
| default: |
| throw new ClassCastException(); |
| } |
| } |
| |
| /** |
| * Returns data in any numerical format as a float. Data in |
| * TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated by |
| * dividing the numerator into the denominator using |
| * double-precision arithmetic. |
| * |
| * <p> A ClassCastException will be thrown if the field is of |
| * type TIFF_UNDEFINED or TIFF_ASCII. |
| */ |
| public double getAsDouble(int index) { |
| switch (type) { |
| case TIFF_BYTE: |
| return ((byte[])data)[index] & 0xff; |
| case TIFF_SBYTE: |
| return ((byte[])data)[index]; |
| case TIFF_SHORT: |
| return ((char[])data)[index] & 0xffff; |
| case TIFF_SSHORT: |
| return ((short[])data)[index]; |
| case TIFF_SLONG: |
| return ((int[])data)[index]; |
| case TIFF_LONG: |
| return ((long[])data)[index]; |
| case TIFF_FLOAT: |
| return ((float[])data)[index]; |
| case TIFF_DOUBLE: |
| return ((double[])data)[index]; |
| case TIFF_SRATIONAL: |
| int[] ivalue = getAsSRational(index); |
| return (double)ivalue[0]/ivalue[1]; |
| case TIFF_RATIONAL: |
| long[] lvalue = getAsRational(index); |
| return (double)lvalue[0]/lvalue[1]; |
| default: |
| throw new ClassCastException(); |
| } |
| } |
| |
| /** |
| * Returns a TIFF_ASCII data item as a String. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_ASCII. |
| */ |
| public String getAsString(int index) { |
| return ((String[])data)[index]; |
| } |
| |
| /** |
| * Returns a TIFF_SRATIONAL data item as a two-element array |
| * of ints. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_SRATIONAL. |
| */ |
| public int[] getAsSRational(int index) { |
| return ((int[][])data)[index]; |
| } |
| |
| /** |
| * Returns a TIFF_RATIONAL data item as a two-element array |
| * of ints. |
| * |
| * <p> A ClassCastException will be thrown if the field is not |
| * of type TIFF_RATIONAL. |
| */ |
| public long[] getAsRational(int index) { |
| return ((long[][])data)[index]; |
| } |
| |
| /** |
| * Compares this <code>TIFFField</code> with another |
| * <code>TIFFField</code> by comparing the tags. |
| * |
| * <p><b>Note: this class has a natural ordering that is inconsistent |
| * with <code>equals()</code>.</b> |
| * |
| * @throws IllegalArgumentException if the parameter is <code>null</code>. |
| * @throws ClassCastException if the parameter is not a |
| * <code>TIFFField</code>. |
| */ |
| public int compareTo(Object o) { |
| if(o == null) { |
| throw new IllegalArgumentException(); |
| } |
| |
| int oTag = ((TIFFField)o).getTag(); |
| |
| if(tag < oTag) { |
| return -1; |
| } else if(tag > oTag) { |
| return 1; |
| } else { |
| return 0; |
| } |
| } |
| } |