com.github.jaiimageio.plugins.tiff.TIFFField Maven / Gradle / Ivy
Show all versions of jai-imageio-core Show documentation
/*
* $RCSfile: TIFFField.java,v $
*
*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
* NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
* ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
* CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
* REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
* INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for
* use in the design, construction, operation or maintenance of any
* nuclear facility.
*
* $Revision: 1.4 $
* $Date: 2006/04/28 01:28:49 $
* $State: Exp $
*/
package com.github.jaiimageio.plugins.tiff;
import java.io.IOException;
import java.io.Serializable;
import java.util.StringTokenizer;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.github.jaiimageio.impl.plugins.tiff.TIFFFieldNode;
import com.github.jaiimageio.plugins.tiff.TIFFTag;
import com.github.jaiimageio.plugins.tiff.TIFFTagSet;
/**
* A class representing a field in a TIFF 6.0 Image File Directory.
*
* A field in a TIFF Image File Directory (IFD) is defined as a
* tag number accompanied by a sequence of values of identical data type.
* TIFF 6.0 defines 12 data types; a 13th type IFD
is
* defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These
* TIFF data types are referred to by Java constants and mapped internally
* onto Java language data types and type names as follows:
*
*
*
*
*
*
*
* TIFF Data Type
*
*
* Java Constant
*
*
* Java Data Type
*
*
* Java Type Name
*
*
*
*
*
* BYTE
*
*
* {@link TIFFTag#TIFF_BYTE}
*
*
* byte
*
*
* "Byte"
*
*
*
*
*
* ASCII
*
*
* {@link TIFFTag#TIFF_ASCII}
*
*
* String
*
*
* "Ascii"
*
*
*
*
*
* SHORT
*
*
* {@link TIFFTag#TIFF_SHORT}
*
*
* char
*
*
* "Short"
*
*
*
*
*
* LONG
*
*
* {@link TIFFTag#TIFF_LONG}
*
*
* long
*
*
* "Long"
*
*
*
*
*
* RATIONAL
*
*
* {@link TIFFTag#TIFF_RATIONAL}
*
*
* long[2]
{numerator, denominator}
*
*
* "Rational"
*
*
*
*
*
* SBYTE
*
*
* {@link TIFFTag#TIFF_SBYTE}
*
*
* byte
*
*
* "SByte"
*
*
*
*
*
* UNDEFINED
*
*
* {@link TIFFTag#TIFF_UNDEFINED}
*
*
* byte
*
*
* "Undefined"
*
*
*
*
*
* SSHORT
*
*
* {@link TIFFTag#TIFF_SSHORT}
*
*
* short
*
*
* "SShort"
*
*
*
*
*
* SLONG
*
*
* {@link TIFFTag#TIFF_SLONG}
*
*
* int
*
*
* "SLong"
*
*
*
*
*
* SRATIONAL
*
*
* {@link TIFFTag#TIFF_SRATIONAL}
*
*
* int[2]
{numerator, denominator}
*
*
* "SRational"
*
*
*
*
*
* FLOAT
*
*
* {@link TIFFTag#TIFF_FLOAT}
*
*
* float
*
*
* "Float"
*
*
*
*
*
* DOUBLE
*
*
* {@link TIFFTag#TIFF_DOUBLE}
*
*
* double
*
*
* "Double"
*
*
*
*
*
* IFD
*
*
* {@link TIFFTag#TIFF_IFD_POINTER}
*
*
* long
*
*
* "IFDPointer"
*
*
*
*
*
* @see TIFFDirectory
* @see TIFFTag
*/
public class TIFFField implements Comparable {
private static final String[] typeNames = {
null,
"Byte", "Ascii", "Short", "Long", "Rational",
"SByte", "Undefined", "SShort", "SLong", "SRational",
"Float", "Double", "IFDPointer"
};
private static final boolean[] isIntegral = {
false,
true, false, true, true, false,
true, true, true, true, false,
false, false, false
};
/** The tag. */
private TIFFTag tag;
/** The tag number. */
private int tagNumber;
/** The tag type. */
private int type;
/** The number of data items present in the field. */
private int count;
/** The field data. */
private Object data;
/** The default constructor. */
private TIFFField() {}
private static String getAttribute(Node node, String attrName) {
NamedNodeMap attrs = node.getAttributes();
return attrs.getNamedItem(attrName).getNodeValue();
}
private static void initData(Node node,
int[] otype, int[] ocount, Object[] odata) {
int type;
int count;
Object data = null;
String typeName = node.getNodeName();
typeName = typeName.substring(4);
typeName = typeName.substring(0, typeName.length() - 1);
type = TIFFField.getTypeByName(typeName);
if (type == -1) {
throw new IllegalArgumentException("typeName = " + typeName);
}
Node child = node.getFirstChild();
count = 0;
while (child != null) {
String childTypeName = child.getNodeName().substring(4);
if (!typeName.equals(childTypeName)) {
// warning
}
++count;
child = child.getNextSibling();
}
if (count > 0) {
data = createArrayForType(type, count);
child = node.getFirstChild();
int idx = 0;
while (child != null) {
String value = getAttribute(child, "value");
String numerator, denominator;
int slashPos;
switch (type) {
case TIFFTag.TIFF_ASCII:
((String[])data)[idx] = value;
break;
case TIFFTag.TIFF_BYTE:
case TIFFTag.TIFF_SBYTE:
((byte[])data)[idx] =
(byte)Integer.parseInt(value);
break;
case TIFFTag.TIFF_SHORT:
((char[])data)[idx] =
(char)Integer.parseInt(value);
break;
case TIFFTag.TIFF_SSHORT:
((short[])data)[idx] =
(short)Integer.parseInt(value);
break;
case TIFFTag.TIFF_SLONG:
((int[])data)[idx] =
(int)Integer.parseInt(value);
break;
case TIFFTag.TIFF_LONG:
case TIFFTag.TIFF_IFD_POINTER:
((long[])data)[idx] =
(long)Long.parseLong(value);
break;
case TIFFTag.TIFF_FLOAT:
((float[])data)[idx] =
(float)Float.parseFloat(value);
break;
case TIFFTag.TIFF_DOUBLE:
((double[])data)[idx] =
(double)Double.parseDouble(value);
break;
case TIFFTag.TIFF_SRATIONAL:
slashPos = value.indexOf("/");
numerator = value.substring(0, slashPos);
denominator = value.substring(slashPos + 1);
((int[][])data)[idx] = new int[2];
((int[][])data)[idx][0] =
Integer.parseInt(numerator);
((int[][])data)[idx][1] =
Integer.parseInt(denominator);
break;
case TIFFTag.TIFF_RATIONAL:
slashPos = value.indexOf("/");
numerator = value.substring(0, slashPos);
denominator = value.substring(slashPos + 1);
((long[][])data)[idx] = new long[2];
((long[][])data)[idx][0] =
Long.parseLong(numerator);
((long[][])data)[idx][1] =
Long.parseLong(denominator);
break;
default:
// error
}
idx++;
child = child.getNextSibling();
}
}
otype[0] = type;
ocount[0] = count;
odata[0] = data;
}
/**
* Creates a TIFFField
from a TIFF native image
* metadata node. If the value of the "tagNumber" attribute
* of the node is not found in tagSet
then a new
* TIFFTag
with name "unknown"
will be
* created and assigned to the field.
*
* @param tagSet The TIFFTagSet
to which the
* TIFFTag
of the field belongs.
* @param node A native TIFF image metadata TIFFField
node.
* @throws IllegalArgumentException if node
is
* null
.
* @throws IllegalArgumentException if the name of the node is not
* "TIFFField"
.
*/
public static TIFFField createFromMetadataNode(TIFFTagSet tagSet,
Node node) {
if (node == null) {
throw new IllegalArgumentException("node == null!");
}
String name = node.getNodeName();
if (!name.equals("TIFFField")) {
throw new IllegalArgumentException("!name.equals(\"TIFFField\")");
}
int tagNumber = Integer.parseInt(getAttribute(node, "number"));
TIFFTag tag;
if (tagSet != null) {
tag = tagSet.getTag(tagNumber);
} else {
tag = new TIFFTag("unknown", tagNumber, 0, null);
}
int type = TIFFTag.TIFF_UNDEFINED;
int count = 0;
Object data = null;
Node child = node.getFirstChild();
if (child != null) {
String typeName = child.getNodeName();
if (typeName.equals("TIFFUndefined")) {
String values = getAttribute(child, "value");
StringTokenizer st = new StringTokenizer(values, ",");
count = st.countTokens();
byte[] bdata = new byte[count];
for (int i = 0; i < count; i++) {
bdata[i] = (byte)Integer.parseInt(st.nextToken());
}
type = TIFFTag.TIFF_UNDEFINED;
data = bdata;
} else {
int[] otype = new int[1];
int[] ocount = new int[1];
Object[] odata = new Object[1];
initData(node.getFirstChild(), otype, ocount, odata);
type = otype[0];
count = ocount[0];
data = odata[0];
}
} else {
int t = TIFFTag.MAX_DATATYPE;
while(t >= TIFFTag.MIN_DATATYPE && !tag.isDataTypeOK(t)) {
t--;
}
type = t;
}
return new TIFFField(tag, type, count, data);
}
/**
* Constructs a TIFFField
with arbitrary data. The
* type
parameter must be a value for which
* {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()
}
* returns true
. The data
parameter must
* be an array of a Java type appropriate for the type of the TIFF
* field unless {@link TIFFTag#isIFDPointer
* tag.isIFDPointer()
} returns true
in
* which case it must be a TIFFDirectory
instance.
*
* Neither the legality of type
with respect to
* tag
nor that or data
with respect to
* type
is verified by this constructor. The methods
* {@link TIFFTag#isDataTypeOK TIFFTag.isDataTypeOK()
}
* and {@link #createArrayForType createArrayForType()
}
* should be used programmatically to ensure that subsequent errors
* such as ClassCastException
s do not occur as a result
* of providing inconsitent parameters to this constructor.
*
* Note that the value (data) of the TIFFField
* will always be the actual field value regardless of the number of
* bytes required for that value. This is the case despite the fact
* that the TIFF IFD Entry corresponding to the field may
* actually contain the offset to the field's value rather than
* the value itself (the latter occurring if and only if the
* value fits into 4 bytes). In other words, the value of the
* field will already have been read from the TIFF stream. This
* subsumes the case where tag.isIFDPointer()
returns
* true
and the value will be a TIFFDirectory
* rather than an array.
*
* @param tag The tag to associated with this field.
* @param type One of the TIFFTag.TIFF_*
constants
* indicating the data type of the field as written to the TIFF stream.
* @param count The number of data values.
* @param data The actual data content of the field.
*
* @throws IllegalArgumentException if tag == null
.
* @throws IllegalArgumentException if dataType
is not
* one of the TIFFTag.TIFF_*
data type constants.
* @throws IllegalArgumentException if count < 0
.
*/
public TIFFField(TIFFTag tag, int type, int count, Object data) {
if(tag == null) {
throw new IllegalArgumentException("tag == null!");
} else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) {
throw new IllegalArgumentException("Unknown data type "+type);
} else if(count < 0) {
throw new IllegalArgumentException("count < 0!");
}
this.tag = tag;
this.tagNumber = tag.getNumber();
this.type = type;
this.count = count;
this.data = data;
}
/**
* Constructs a data array using {@link #createArrayForType
* createArrayForType()
} and invokes
* {@link #TIFFField(TIFFTag,int,int,Object)} with the supplied
* parameters and the created array.
*
* @see #TIFFField(TIFFTag,int,int,Object)
*/
public TIFFField(TIFFTag tag, int type, int count) {
this(tag, type, count, createArrayForType(type, count));
}
/**
* Constructs a TIFFField
with a single integral value.
* The field will have type
* {@link TIFFTag#TIFF_SHORT TIFF_SHORT
} if
* val < 65536
and type
* {@link TIFFTag#TIFF_LONG TIFF_LONG
} otherwise.
* It is not verified whether the resulting type is
* legal for tag
.
*
* @param tag The tag to associate with this field.
* @param value The value to associate with this field.
* @throws IllegalArgumentException if tag == null
.
* @throws IllegalArgumentException if value < 0
.
*/
public TIFFField(TIFFTag tag, int value) {
if(tag == null) {
throw new IllegalArgumentException("tag == null!");
}
if (value < 0) {
throw new IllegalArgumentException("value < 0!");
}
this.tag = tag;
this.tagNumber = tag.getNumber();
this.count = 1;
if (value < 65536) {
this.type = TIFFTag.TIFF_SHORT;
char[] cdata = new char[1];
cdata[0] = (char)value;
this.data = cdata;
} else {
this.type = TIFFTag.TIFF_LONG;
long[] ldata = new long[1];
ldata[0] = value;
this.data = ldata;
}
}
/**
* Retrieves the tag associated with this field.
*
* @return The associated TIFFTag
.
*/
public TIFFTag getTag() {
return tag;
}
/**
* Retrieves the tag number in the range [0, 65535]
.
*
* @return The tag number.
*/
public int getTagNumber() {
return tagNumber;
}
/**
* Returns the type of the data stored in the field. For a TIFF 6.0
* stream, the value will equal one of the TIFFTag.TIFF_*
* constants. For future revisions of TIFF, higher values are possible.
*
* @return The data type of the field value.
*/
public int getType() {
return type;
}
/**
* Returns the name of the supplied data type constant.
*
* @param dataType One of the TIFFTag.TIFF_*
constants
* indicating the data type of the field as written to the TIFF stream.
* @return The type name corresponding to the supplied type constant.
* @throws IllegalArgumentException if dataType
is not
* one of the TIFFTag.TIFF_*
data type constants.
*/
public static String getTypeName(int dataType) {
if (dataType < TIFFTag.MIN_DATATYPE ||
dataType > TIFFTag.MAX_DATATYPE) {
throw new IllegalArgumentException("Unknown data type "+dataType);
}
return typeNames[dataType];
}
/**
* Returns the data type constant corresponding to the supplied data
* type name. If the name is unknown -1
will be returned.
*
* @return One of the TIFFTag.TIFF_*
constants or
* -1
if the name is not recognized.
*/
public static int getTypeByName(String typeName) {
for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
if (typeName.equals(typeNames[i])) {
return i;
}
}
return -1;
}
/**
* Creates an array appropriate for the indicated data type.
*
* @param dataType One of the TIFFTag.TIFF_*
data type
* constants.
* @param count The number of values in the array.
*
* @throws IllegalArgumentException if dataType
is not
* one of the TIFFTag.TIFF_*
data type constants.
* @throws IllegalArgumentException if count < 0
.
*/
public static Object createArrayForType(int dataType, int count) {
if(count < 0) {
throw new IllegalArgumentException("count < 0!");
}
switch (dataType) {
case TIFFTag.TIFF_BYTE:
case TIFFTag.TIFF_SBYTE:
case TIFFTag.TIFF_UNDEFINED:
return new byte[count];
case TIFFTag.TIFF_ASCII:
return new String[count];
case TIFFTag.TIFF_SHORT:
return new char[count];
case TIFFTag.TIFF_LONG:
case TIFFTag.TIFF_IFD_POINTER:
return new long[count];
case TIFFTag.TIFF_RATIONAL:
return new long[count][2];
case TIFFTag.TIFF_SSHORT:
return new short[count];
case TIFFTag.TIFF_SLONG:
return new int[count];
case TIFFTag.TIFF_SRATIONAL:
return new int[count][2];
case TIFFTag.TIFF_FLOAT:
return new float[count];
case TIFFTag.TIFF_DOUBLE:
return new double[count];
default:
throw new IllegalArgumentException("Unknown data type "+dataType);
}
}
/**
* Returns the TIFFField
as a node named either
* "TIFFField" or "TIFFIFD" as described in the
* TIFF native image metadata specification. The node will be named
* "TIFFIFD" if and only if the field's data object is an
* instance of {@link TIFFDirectory} or equivalently
* {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns
* true
.
*
* @return a Node
named "TIFFField" or
* "TIFFIFD".
*/
public Node getAsNativeNode() {
return new TIFFFieldNode(this);
}
/**
* Indicates whether the value associated with the field is of
* integral data type.
*
* @return Whether the field type is integral.
*/
public boolean isIntegral() {
return isIntegral[type];
}
/**
* Returns the number of data items present in the field. For
* TIFFTag.TIFF_ASCII
fields, the value returned is the
* number of String
s, not the total length of the
* data as in the file representation.
*/
public int getCount() {
return count;
}
/**
* Returns a reference to the data object associated with the field.
*
* @return The data object of the field.
*/
public Object getData() {
return data;
}
/**
* Returns the data as an uninterpreted array of
* byte
s. The type of the field must be one of
* TIFFTag.TIFF_BYTE
, TIFF_SBYTE
, or
* TIFF_UNDEFINED
.
*
* For data in TIFFTag.TIFF_BYTE
format, the application
* must take care when promoting the data to longer integral types
* to avoid sign extension.
*
* @throws ClassCastException if the field is not of type
* TIFF_BYTE
, TIFF_SBYTE
, or
* TIFF_UNDEFINED
.
*/
public byte[] getAsBytes() {
return (byte[])data;
}
/**
* Returns TIFFTag.TIFF_SHORT
data as an array of
* char
s (unsigned 16-bit integers).
*
* @throws ClassCastException if the field is not of type
* TIFF_SHORT
.
*/
public char[] getAsChars() {
return (char[])data;
}
/**
* Returns TIFFTag.TIFF_SSHORT
data as an array of
* short
s (signed 16-bit integers).
*
* @throws ClassCastException if the field is not of type
* TIFF_SSHORT
.
*/
public short[] getAsShorts() {
return (short[])data;
}
/**
* Returns TIFFTag.TIFF_SLONG
data as an array of
* int
s (signed 32-bit integers).
*
* @throws ClassCastException if the field is not of type
* TIFF_SHORT
, TIFF_SSHORT
, or
* TIFF_SLONG
.
*/
public int[] getAsInts() {
if (data instanceof int[]) {
return (int[])data;
} else if (data instanceof char[]){
char[] cdata = (char[])data;
int[] idata = new int[cdata.length];
for (int i = 0; i < cdata.length; i++) {
idata[i] = (int)(cdata[i] & 0xffff);
}
return idata;
} else if (data instanceof short[]){
short[] sdata = (short[])data;
int[] idata = new int[sdata.length];
for (int i = 0; i < sdata.length; i++) {
idata[i] = (int)sdata[i];
}
return idata;
} else {
throw new ClassCastException(
"Data not char[], short[], or int[]!");
}
}
/**
* Returns TIFFTag.TIFF_LONG
or
* TIFF_IFD_POINTER
data as an array of
* long
s (signed 64-bit integers).
*
* @throws ClassCastException if the field is not of type
* TIFF_LONG
or TIFF_IFD_POINTER
.
*/
public long[] getAsLongs() {
return (long[])data;
}
/**
* Returns TIFFTag.TIFF_FLOAT
data as an array of
* float
s (32-bit floating-point values).
*
* @throws ClassCastException if the field is not of type
* TIFF_FLOAT
.
*/
public float[] getAsFloats() {
return (float[])data;
}
/**
* Returns TIFFTag.TIFF_DOUBLE
data as an array of
* double
s (64-bit floating-point values).
*
* @throws ClassCastException if the field is not of type
* TIFF_DOUBLE
.
*/
public double[] getAsDoubles() {
return (double[])data;
}
/**
* Returns TIFFTag.TIFF_SRATIONAL
data as an array of
* 2-element arrays of int
s.
*
* @throws ClassCastException if the field is not of type
* TIFF_SRATIONAL
.
*/
public int[][] getAsSRationals() {
return (int[][])data;
}
/**
* Returns TIFFTag.TIFF_RATIONAL
data as an array of
* 2-element arrays of long
s.
*
* @throws ClassCastException if the field is not of type
* TIFF_RATIONAL
.
*/
public long[][] getAsRationals() {
return (long[][])data;
}
/**
* Returns data in any format as an int
.
*
*
TIFFTag.TIFF_BYTE
values 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].
*
*
A TIFF_UNDEFINED
value is treated as though
* it were a TIFF_BYTE
.
*
*
Data in TIFF_SLONG
, TIFF_LONG
,
* TIFF_FLOAT
, TIFF_DOUBLE
or
* TIFF_IFD_POINTER
format are simply cast to
* int
and may suffer from truncation.
*
*
Data in TIFF_SRATIONAL
or
* TIFF_RATIONAL
format are evaluated by dividing the
* numerator into the denominator using double-precision
* arithmetic and then casting to int
. Loss of
* precision and truncation may occur.
*
*
Data in TIFF_ASCII
format will be parsed as by
* the Double.parseDouble
method, with the result
* case to int
.
*/
public int getAsInt(int index) {
switch (type) {
case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
return ((byte[])data)[index] & 0xff;
case TIFFTag.TIFF_SBYTE:
return ((byte[])data)[index];
case TIFFTag.TIFF_SHORT:
return ((char[])data)[index] & 0xffff;
case TIFFTag.TIFF_SSHORT:
return ((short[])data)[index];
case TIFFTag.TIFF_SLONG:
return ((int[])data)[index];
case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
return (int)((long[])data)[index];
case TIFFTag.TIFF_FLOAT:
return (int)((float[])data)[index];
case TIFFTag.TIFF_DOUBLE:
return (int)((double[])data)[index];
case TIFFTag.TIFF_SRATIONAL:
int[] ivalue = getAsSRational(index);
return (int)((double)ivalue[0]/ivalue[1]);
case TIFFTag.TIFF_RATIONAL:
long[] lvalue = getAsRational(index);
return (int)((double)lvalue[0]/lvalue[1]);
case TIFFTag.TIFF_ASCII:
String s = ((String[])data)[index];
return (int)Double.parseDouble(s);
default:
throw new ClassCastException();
}
}
/**
* Returns data in any format as a long
.
*
*
TIFFTag.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].
*
*
Data in TIFF_ASCII
format will be parsed as by
* the Double.parseDouble
method, with the result
* cast to long
.
*/
public long getAsLong(int index) {
switch (type) {
case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
return ((byte[])data)[index] & 0xff;
case TIFFTag.TIFF_SBYTE:
return ((byte[])data)[index];
case TIFFTag.TIFF_SHORT:
return ((char[])data)[index] & 0xffff;
case TIFFTag.TIFF_SSHORT:
return ((short[])data)[index];
case TIFFTag.TIFF_SLONG:
return ((int[])data)[index];
case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
return ((long[])data)[index];
case TIFFTag.TIFF_SRATIONAL:
int[] ivalue = getAsSRational(index);
return (long)((double)ivalue[0]/ivalue[1]);
case TIFFTag.TIFF_RATIONAL:
long[] lvalue = getAsRational(index);
return (long)((double)lvalue[0]/lvalue[1]);
case TIFFTag.TIFF_ASCII:
String s = ((String[])data)[index];
return (long)Double.parseDouble(s);
default:
throw new ClassCastException();
}
}
/**
* Returns data in any format as a float
.
*
*
TIFFTag.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].
*
*
Data in TIFF_SLONG
, TIFF_LONG
,
* TIFF_DOUBLE
, or TIFF_IFD_POINTER
format are
* simply cast to float
and may suffer from
* truncation.
*
*
Data in TIFF_SRATIONAL
or
* TIFF_RATIONAL
format are evaluated by dividing the
* numerator into the denominator using double-precision
* arithmetic and then casting to float
.
*
*
Data in TIFF_ASCII
format will be parsed as by
* the Double.parseDouble
method, with the result
* cast to float
.
*/
public float getAsFloat(int index) {
switch (type) {
case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
return ((byte[])data)[index] & 0xff;
case TIFFTag.TIFF_SBYTE:
return ((byte[])data)[index];
case TIFFTag.TIFF_SHORT:
return ((char[])data)[index] & 0xffff;
case TIFFTag.TIFF_SSHORT:
return ((short[])data)[index];
case TIFFTag.TIFF_SLONG:
return ((int[])data)[index];
case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
return ((long[])data)[index];
case TIFFTag.TIFF_FLOAT:
return ((float[])data)[index];
case TIFFTag.TIFF_DOUBLE:
return (float)((double[])data)[index];
case TIFFTag.TIFF_SRATIONAL:
int[] ivalue = getAsSRational(index);
return (float)((double)ivalue[0]/ivalue[1]);
case TIFFTag.TIFF_RATIONAL:
long[] lvalue = getAsRational(index);
return (float)((double)lvalue[0]/lvalue[1]);
case TIFFTag.TIFF_ASCII:
String s = ((String[])data)[index];
return (float)Double.parseDouble(s);
default:
throw new ClassCastException();
}
}
/**
* Returns data in any format as a double
.
*
*
TIFFTag.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].
*
*
Data in TIFF_SRATIONAL
or
* TIFF_RATIONAL
format are evaluated by dividing the
* numerator into the denominator using double-precision
* arithmetic.
*
*
Data in TIFF_ASCII
format will be parsed as by
* the Double.parseDouble
method.
*/
public double getAsDouble(int index) {
switch (type) {
case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
return ((byte[])data)[index] & 0xff;
case TIFFTag.TIFF_SBYTE:
return ((byte[])data)[index];
case TIFFTag.TIFF_SHORT:
return ((char[])data)[index] & 0xffff;
case TIFFTag.TIFF_SSHORT:
return ((short[])data)[index];
case TIFFTag.TIFF_SLONG:
return ((int[])data)[index];
case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
return ((long[])data)[index];
case TIFFTag.TIFF_FLOAT:
return ((float[])data)[index];
case TIFFTag.TIFF_DOUBLE:
return ((double[])data)[index];
case TIFFTag.TIFF_SRATIONAL:
int[] ivalue = getAsSRational(index);
return (double)ivalue[0]/ivalue[1];
case TIFFTag.TIFF_RATIONAL:
long[] lvalue = getAsRational(index);
return (double)lvalue[0]/lvalue[1];
case TIFFTag.TIFF_ASCII:
String s = ((String[])data)[index];
return Double.parseDouble(s);
default:
throw new ClassCastException();
}
}
/**
* Returns a TIFFTag.TIFF_ASCII
value as a
* String
.
*
* @throws ClassCastException if the field is not of type
* TIFF_ASCII
.
*/
public String getAsString(int index) {
return ((String[])data)[index];
}
/**
* Returns a TIFFTag.TIFF_SRATIONAL
data item as a
* two-element array of int
s.
*
* @throws ClassCastException if the field is not of type
* TIFF_SRATIONAL
.
*/
public int[] getAsSRational(int index) {
return ((int[][])data)[index];
}
/**
* Returns a TIFFTag.TIFF_RATIONAL data item as a two-element array
* of ints.
*
* @throws ClassCastException if the field is not of type
* TIFF_RATIONAL
.
*/
public long[] getAsRational(int index) {
return ((long[][])data)[index];
}
/**
* Returns a String
containing a human-readable
* version of the data item. Data of type
* TIFFTag.TIFF_RATIONAL
or TIFF_SRATIONAL
are
* represented as a pair of integers separated by a
* '/'
character.
*
* @throws ClassCastException if the field is not of one of the
* legal field types.
*/
public String getValueAsString(int index) {
switch (type) {
case TIFFTag.TIFF_ASCII:
return ((String[])data)[index];
case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
return Integer.toString(((byte[])data)[index] & 0xff);
case TIFFTag.TIFF_SBYTE:
return Integer.toString(((byte[])data)[index]);
case TIFFTag.TIFF_SHORT:
return Integer.toString(((char[])data)[index] & 0xffff);
case TIFFTag.TIFF_SSHORT:
return Integer.toString(((short[])data)[index]);
case TIFFTag.TIFF_SLONG:
return Integer.toString(((int[])data)[index]);
case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
return Long.toString(((long[])data)[index]);
case TIFFTag.TIFF_FLOAT:
return Float.toString(((float[])data)[index]);
case TIFFTag.TIFF_DOUBLE:
return Double.toString(((double[])data)[index]);
case TIFFTag.TIFF_SRATIONAL:
int[] ivalue = getAsSRational(index);
String srationalString;
if(ivalue[1] != 0 && ivalue[0] % ivalue[1] == 0) {
// If the denominator is a non-zero integral divisor
// of the numerator then convert the fraction to be
// with respect to a unity denominator.
srationalString =
Integer.toString(ivalue[0] / ivalue[1]) + "/1";
} else {
// Use the values directly.
srationalString =
Integer.toString(ivalue[0]) +
"/" +
Integer.toString(ivalue[1]);
}
return srationalString;
case TIFFTag.TIFF_RATIONAL:
long[] lvalue = getAsRational(index);
String rationalString;
if(lvalue[1] != 0L && lvalue[0] % lvalue[1] == 0) {
// If the denominator is a non-zero integral divisor
// of the numerator then convert the fraction to be
// with respect to a unity denominator.
rationalString =
Long.toString(lvalue[0] / lvalue[1]) + "/1";
} else {
// Use the values directly.
rationalString =
Long.toString(lvalue[0]) +
"/" +
Long.toString(lvalue[1]);
}
return rationalString;
default:
throw new ClassCastException();
}
}
/**
* Compares this TIFFField
with another
* TIFFField
by comparing the tags.
*
*
Note: this class has a natural ordering that is inconsistent
* with equals()
.
*
* @throws IllegalArgumentException if the parameter is null
.
* @throws ClassCastException if the parameter is not a
* TIFFField
.
*/
public int compareTo(Object o) {
if (o == null) {
throw new IllegalArgumentException();
}
int oTagNumber = ((TIFFField)o).getTagNumber();
if (tagNumber < oTagNumber) {
return -1;
} else if (tagNumber > oTagNumber) {
return 1;
} else {
return 0;
}
}
}