All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jaiimageio.plugins.tiff.TIFFField Maven / Gradle / Ivy

Go to download

Java Advanced Imaging Image I/O Tools API core, but without the classes involved with javax.media.jai dependencies, JPEG2000 or codecLibJIIO, meaning that this library can be distributed under the modified BSD license and should be GPL compatible.

The newest version!
/*
 * $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 ClassCastExceptions 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 Strings, 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 * bytes. 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 * chars (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 * shorts (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 * ints (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 * longs (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 * floats (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 * doubles (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 ints. * * @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 longs. * * @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 ints. * * @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; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy