1 /*
   2  * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.imageio.plugins.tiff;
  26 
  27 import java.util.StringTokenizer;
  28 import org.w3c.dom.NamedNodeMap;
  29 import org.w3c.dom.Node;
  30 import com.sun.imageio.plugins.tiff.TIFFFieldNode;
  31 import com.sun.imageio.plugins.tiff.TIFFIFD;
  32 
  33 /**
  34  * A class representing a field in a TIFF 6.0 Image File Directory.
  35  *
  36  * <p> A field in a TIFF Image File Directory (IFD) is defined as a
  37  * tag number accompanied by a sequence of values of identical data type.
  38  * TIFF 6.0 defines 12 data types; a 13th type {@code IFD} is
  39  * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These
  40  * TIFF data types are referred to by Java constants and mapped internally
  41  * onto Java language data types and type names as follows:
  42  *
  43  * <table class="striped">
  44  * <caption>TIFF Data Type to Java Data Type Mapping</caption>
  45  * <thead>
  46  *   <tr>
  47  *     <th scope="col">TIFF Data Type
  48  *     <th scope="col">Java Constant
  49  *     <th scope="col">Java Data Type
  50  *     <th scope="col">Java Type Name
  51  * </thead>
  52  * <tbody>
  53  *   <tr>
  54  *     <th scope="row">{@code BYTE}
  55  *     <td>{@link TIFFTag#TIFF_BYTE}
  56  *     <td>{@code byte}
  57  *     <td>{@code "Byte"}
  58  *   <tr>
  59  *     <th scope="row">{@code ASCII}
  60  *     <td>{@link TIFFTag#TIFF_ASCII}
  61  *     <td>{@code String}
  62  *     <td>{@code "Ascii"}
  63  *   <tr>
  64  *     <th scope="row">{@code SHORT}
  65  *     <td>{@link TIFFTag#TIFF_SHORT}
  66  *     <td>{@code char}
  67  *     <td>{@code "Short"}
  68  *   <tr>
  69  *     <th scope="row">{@code LONG}
  70  *     <td>{@link TIFFTag#TIFF_LONG}
  71  *     <td>{@code long}
  72  *     <td>{@code "Long"}
  73  *   <tr>
  74  *     <th scope="row">{@code RATIONAL}
  75  *     <td>{@link TIFFTag#TIFF_RATIONAL}
  76  *     <td>{@code long[2]} {numerator, denominator}
  77  *     <td>{@code "Rational"}
  78  *   <tr>
  79  *     <th scope="row">{@code SBYTE}
  80  *     <td>{@link TIFFTag#TIFF_SBYTE}
  81  *     <td>{@code byte}
  82  *     <td>{@code "SByte"}
  83  *   <tr>
  84  *     <th scope="row">{@code UNDEFINED}
  85  *     <td>{@link TIFFTag#TIFF_UNDEFINED}
  86  *     <td>{@code byte}
  87  *     <td>{@code "Undefined"}
  88  *   <tr>
  89  *     <th scope="row">{@code SSHORT}
  90  *     <td>{@link TIFFTag#TIFF_SSHORT}
  91  *     <td>{@code short}
  92  *     <td>{@code "SShort"}
  93  *   <tr>
  94  *     <th scope="row">{@code SLONG}
  95  *     <td>{@link TIFFTag#TIFF_SLONG}
  96  *     <td>{@code int}
  97  *     <td>{@code "SLong"}
  98  *   <tr>
  99  *     <th scope="row">{@code SRATIONAL}
 100  *     <td>{@link TIFFTag#TIFF_SRATIONAL}
 101  *     <td>{@code int[2]} {numerator, denominator}
 102  *     <td>{@code "SRational"}
 103  *   <tr>
 104  *     <th scope="row">{@code FLOAT}
 105  *     <td>{@link TIFFTag#TIFF_FLOAT}
 106  *     <td>{@code float}
 107  *     <td>{@code "Float"}
 108  *   <tr>
 109  *     <th scope="row">{@code DOUBLE}
 110  *     <td>{@link TIFFTag#TIFF_DOUBLE}
 111  *     <td>{@code double}
 112  *     <td>{@code "Double"}
 113  *   <tr>
 114  *     <th scope="row">{@code IFD}
 115  *     <td>{@link TIFFTag#TIFF_IFD_POINTER}
 116  *     <td>{@code long}
 117  *     <td>{@code "IFDPointer"}
 118  *   </tr>
 119  * </tbody>
 120  * </table>
 121  *
 122  * @since 9
 123  * @see   TIFFDirectory
 124  * @see   TIFFTag
 125  */
 126 public final class TIFFField implements Cloneable {
 127 
 128     private static final long MAX_UINT32 = 0xffffffffL;
 129 
 130     private static final String[] TYPE_NAMES = {
 131         null,
 132         "Byte", "Ascii", "Short", "Long", "Rational",
 133         "SByte", "Undefined", "SShort", "SLong", "SRational",
 134         "Float", "Double", "IFDPointer"
 135     };
 136 
 137     private static final boolean[] IS_INTEGRAL = {
 138         false,
 139         true, false, true, true, false,
 140         true, true, true, true, false,
 141         false, false, false
 142     };
 143 
 144     /** The tag. */
 145     private TIFFTag tag;
 146 
 147     /** The tag number. */
 148     private int tagNumber;
 149 
 150     /** The tag type. */
 151     private int type;
 152 
 153     /** The number of data items present in the field. */
 154     private int count;
 155 
 156     /** The field data. */
 157     private Object data;
 158 
 159     /** The IFD contents if available. This will usually be a TIFFIFD. */
 160     private TIFFDirectory dir;
 161 
 162     /** The default constructor. */
 163     private TIFFField() {}
 164 
 165     private static String getAttribute(Node node, String attrName) {
 166         NamedNodeMap attrs = node.getAttributes();
 167         return attrs.getNamedItem(attrName).getNodeValue();
 168     }
 169 
 170     private static void initData(Node node,
 171                                  int[] otype, int[] ocount, Object[] odata) {
 172         int type;
 173         int count;
 174         Object data = null;
 175 
 176         String typeName = node.getNodeName();
 177         typeName = typeName.substring(4);
 178         typeName = typeName.substring(0, typeName.length() - 1);
 179         type = TIFFField.getTypeByName(typeName);
 180         if (type == -1) {
 181             throw new IllegalArgumentException("typeName = " + typeName);
 182         }
 183 
 184         Node child = node.getFirstChild();
 185 
 186         count = 0;
 187         while (child != null) {
 188             String childTypeName = child.getNodeName().substring(4);
 189             if (!typeName.equals(childTypeName)) {
 190                 // warning
 191             }
 192 
 193             ++count;
 194             child = child.getNextSibling();
 195         }
 196 
 197         if (count > 0) {
 198             data = createArrayForType(type, count);
 199             child = node.getFirstChild();
 200             int idx = 0;
 201             while (child != null) {
 202                 String value = getAttribute(child, "value");
 203 
 204                 String numerator, denominator;
 205                 int slashPos;
 206 
 207                 switch (type) {
 208                 case TIFFTag.TIFF_ASCII:
 209                     ((String[])data)[idx] = value;
 210                     break;
 211                 case TIFFTag.TIFF_BYTE:
 212                 case TIFFTag.TIFF_SBYTE:
 213                     ((byte[])data)[idx] =
 214                         (byte)Integer.parseInt(value);
 215                     break;
 216                 case TIFFTag.TIFF_SHORT:
 217                     ((char[])data)[idx] =
 218                         (char)Integer.parseInt(value);
 219                     break;
 220                 case TIFFTag.TIFF_SSHORT:
 221                     ((short[])data)[idx] =
 222                         (short)Integer.parseInt(value);
 223                     break;
 224                 case TIFFTag.TIFF_SLONG:
 225                     ((int[])data)[idx] =
 226                         Integer.parseInt(value);
 227                     break;
 228                 case TIFFTag.TIFF_LONG:
 229                 case TIFFTag.TIFF_IFD_POINTER:
 230                     ((long[])data)[idx] =
 231                         Long.parseLong(value);
 232                     break;
 233                 case TIFFTag.TIFF_FLOAT:
 234                     ((float[])data)[idx] =
 235                         Float.parseFloat(value);
 236                     break;
 237                 case TIFFTag.TIFF_DOUBLE:
 238                     ((double[])data)[idx] =
 239                         Double.parseDouble(value);
 240                     break;
 241                 case TIFFTag.TIFF_SRATIONAL:
 242                     slashPos = value.indexOf("/");
 243                     numerator = value.substring(0, slashPos);
 244                     denominator = value.substring(slashPos + 1);
 245 
 246                     ((int[][])data)[idx] = new int[2];
 247                     ((int[][])data)[idx][0] =
 248                         Integer.parseInt(numerator);
 249                     ((int[][])data)[idx][1] =
 250                         Integer.parseInt(denominator);
 251                     break;
 252                 case TIFFTag.TIFF_RATIONAL:
 253                     slashPos = value.indexOf("/");
 254                     numerator = value.substring(0, slashPos);
 255                     denominator = value.substring(slashPos + 1);
 256 
 257                     ((long[][])data)[idx] = new long[2];
 258                     ((long[][])data)[idx][0] =
 259                         Long.parseLong(numerator);
 260                     ((long[][])data)[idx][1] =
 261                         Long.parseLong(denominator);
 262                     break;
 263                 default:
 264                     // error
 265                 }
 266 
 267                 idx++;
 268                 child = child.getNextSibling();
 269             }
 270         }
 271 
 272         otype[0] = type;
 273         ocount[0] = count;
 274         odata[0] = data;
 275     }
 276 
 277     /**
 278      * Creates a {@code TIFFField} from a TIFF native image
 279      * metadata node. If the value of the {@code "number"} attribute
 280      * of the node is not found in {@code tagSet} then a new
 281      * {@code TIFFTag} with name {@code TIFFTag.UNKNOWN_TAG_NAME}
 282      * will be created and assigned to the field.
 283      *
 284      * @param tagSet The {@code TIFFTagSet} to which the
 285      * {@code TIFFTag} of the field belongs.
 286      * @param node A native TIFF image metadata {@code TIFFField} node.
 287      * @throws IllegalArgumentException If the {@code Node} parameter content
 288      * does not adhere to the {@code TIFFField} element structure defined by
 289      * the <a href="../../metadata/doc-files/tiff_metadata.html#ImageMetadata">
 290      * TIFF native image metadata format specification</a>, or if the
 291      * combination of node attributes and data is not legal per the
 292      * {@link #TIFFField(TIFFTag,int,int,Object)} constructor specification.
 293      * Note that a cause might be set on such an exception.
 294      * @return A new {@code TIFFField}.
 295      */
 296     public static TIFFField createFromMetadataNode(TIFFTagSet tagSet,
 297                                                    Node node) {
 298         if (node == null) {
 299             // This method is specified to throw only IllegalArgumentExceptions
 300             // so we create an IAE with a NullPointerException as its cause.
 301             throw new IllegalArgumentException(new NullPointerException
 302                 ("node == null!"));
 303         }
 304         String name = node.getNodeName();
 305         if (!name.equals("TIFFField")) {
 306             throw new IllegalArgumentException("!name.equals(\"TIFFField\")");
 307         }
 308 
 309         int tagNumber = Integer.parseInt(getAttribute(node, "number"));
 310         TIFFTag tag = null;
 311         if (tagSet != null) {
 312             tag = tagSet.getTag(tagNumber);
 313         }
 314 
 315         int type = TIFFTag.TIFF_UNDEFINED;
 316         int count = 0;
 317         Object data = null;
 318 
 319         Node child = node.getFirstChild();
 320         if (child != null) {
 321             String typeName = child.getNodeName();
 322             if (typeName.equals("TIFFUndefined")) {
 323                 String values = getAttribute(child, "value");
 324                 StringTokenizer st = new StringTokenizer(values, ",");
 325                 count = st.countTokens();
 326 
 327                 byte[] bdata = new byte[count];
 328                 for (int i = 0; i < count; i++) {
 329                     bdata[i] = (byte)Integer.parseInt(st.nextToken());
 330                 }
 331 
 332                 type = TIFFTag.TIFF_UNDEFINED;
 333                 data = bdata;
 334             } else {
 335                 int[] otype = new int[1];
 336                 int[] ocount = new int[1];
 337                 Object[] odata = new Object[1];
 338 
 339                 initData(node.getFirstChild(), otype, ocount, odata);
 340                 type = otype[0];
 341                 count = ocount[0];
 342                 data = odata[0];
 343             }
 344         } else if (tag != null) {
 345             int t = TIFFTag.MAX_DATATYPE;
 346             while(t >= TIFFTag.MIN_DATATYPE && !tag.isDataTypeOK(t)) {
 347                 t--;
 348             }
 349             type = t;
 350         }
 351 
 352         if (tag == null) {
 353             tag = new TIFFTag(TIFFTag.UNKNOWN_TAG_NAME, tagNumber, 1 << type);
 354         }
 355 
 356         TIFFField field;
 357         try {
 358             field = new TIFFField(tag, type, count, data);
 359         } catch (NullPointerException npe) {
 360             // This method is specified to throw only IllegalArgumentExceptions
 361             // so we catch the NullPointerException and set it as the cause of
 362             // the IAE which is thrown.
 363             throw new IllegalArgumentException(npe);
 364         }
 365 
 366         return field;
 367     }
 368 
 369     /**
 370      * Constructs a {@code TIFFField} with arbitrary data. The
 371      * {@code type} parameter must be a value for which
 372      * {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()}
 373      * returns {@code true}. The {@code data} parameter must
 374      * be an array of a Java type appropriate for the type of the TIFF
 375      * field.
 376      *
 377      * <p>Note that the value (data) of the {@code TIFFField}
 378      * will always be the actual field value regardless of the number of
 379      * bytes required for that value. This is the case despite the fact
 380      * that the TIFF <i>IFD Entry</i> corresponding to the field may
 381      * actually contain the offset to the value of the field rather than
 382      * the value itself (the latter occurring if and only if the
 383      * value fits into 4 bytes). In other words, the value of the
 384      * field will already have been read from the TIFF stream. (An exception
 385      * to this case may occur when the field represents the contents of a
 386      * non-baseline IFD. In that case the data will be a {@code long[]}
 387      * containing the offset to the IFD and the {@code TIFFDirectory}
 388      * returned by {@link #getDirectory()} will be its contents.)
 389      *
 390      * @param tag The tag to associated with this field.
 391      * @param type One of the {@code TIFFTag.TIFF_*} constants
 392      * indicating the data type of the field as written to the TIFF stream.
 393      * @param count The number of data values.
 394      * @param data The actual data content of the field.
 395      *
 396      * @throws NullPointerException if {@code tag == null}.
 397      * @throws IllegalArgumentException if {@code type} is not
 398      * one of the {@code TIFFTag.TIFF_*} data type constants.
 399      * @throws IllegalArgumentException if {@code type} is an unacceptable
 400      * data type for the supplied {@code TIFFTag}.
 401      * @throws IllegalArgumentException if {@code count < 0}.
 402      * @throws IllegalArgumentException if {@code count < 1}
 403      * and {@code type} is {@code TIFF_RATIONAL} or
 404      * {@code TIFF_SRATIONAL}.
 405      * @throws IllegalArgumentException if {@code count != 1}
 406      * and {@code type} is {@code TIFF_IFD_POINTER}.
 407      * @throws NullPointerException if {@code data == null}.
 408      * @throws IllegalArgumentException if {@code data} is an instance of
 409      * a class incompatible with the specified type.
 410      * @throws IllegalArgumentException if the size of the data array is wrong.
 411      * @throws IllegalArgumentException if the type of the data array is
 412      * {@code TIFF_LONG}, {@code TIFF_RATIONAL}, or {@code TIFF_IFD_POINTER}
 413      * and any of the elements is negative or greater than {@code 0xffffffff}.
 414      */
 415     public TIFFField(TIFFTag tag, int type, int count, Object data) {
 416         if(tag == null) {
 417             throw new NullPointerException("tag == null!");
 418         } else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) {
 419             throw new IllegalArgumentException("Unknown data type "+type);
 420         } else if(!tag.isDataTypeOK(type)) {
 421             throw new IllegalArgumentException("Illegal data type " + type
 422                 + " for " + tag.getName() + " tag");
 423         } else if(count < 0) {
 424             throw new IllegalArgumentException("count < 0!");
 425         } else if((type == TIFFTag.TIFF_RATIONAL
 426                    || type == TIFFTag.TIFF_SRATIONAL)
 427                   && count < 1) {
 428             throw new IllegalArgumentException
 429                 ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1");
 430         } else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) {
 431             throw new IllegalArgumentException
 432                 ("Type is TIFF_IFD_POINTER and count != 1");
 433         } else if(data == null) {
 434             throw new NullPointerException("data == null!");
 435         }
 436 
 437         boolean isDataArrayCorrect = false;
 438 
 439         switch (type) {
 440         case TIFFTag.TIFF_BYTE:
 441         case TIFFTag.TIFF_SBYTE:
 442         case TIFFTag.TIFF_UNDEFINED:
 443             isDataArrayCorrect = data instanceof byte[]
 444                 && ((byte[])data).length == count;
 445             break;
 446         case TIFFTag.TIFF_ASCII:
 447             isDataArrayCorrect = data instanceof String[]
 448                 && ((String[])data).length == count;
 449             break;
 450         case TIFFTag.TIFF_SHORT:
 451             isDataArrayCorrect = data instanceof char[]
 452                 && ((char[])data).length == count;
 453             break;
 454         case TIFFTag.TIFF_LONG:
 455             isDataArrayCorrect = data instanceof long[]
 456                 && ((long[])data).length == count;
 457             if (isDataArrayCorrect) {
 458                 for (long datum : (long[])data) {
 459                     if (datum < 0) {
 460                         throw new IllegalArgumentException
 461                             ("Negative value supplied for TIFF_LONG");
 462                     }
 463                     if (datum > MAX_UINT32) {
 464                         throw new IllegalArgumentException
 465                             ("Too large value supplied for TIFF_LONG");
 466                     }
 467                 }
 468             }
 469             break;
 470         case TIFFTag.TIFF_IFD_POINTER:
 471             isDataArrayCorrect = data instanceof long[]
 472                 && ((long[])data).length == 1;
 473             if (((long[])data)[0] < 0) {
 474                 throw new IllegalArgumentException
 475                     ("Negative value supplied for TIFF_IFD_POINTER");
 476             }
 477             if (((long[])data)[0] > MAX_UINT32) {
 478                 throw new IllegalArgumentException
 479                     ("Too large value supplied for TIFF_IFD_POINTER");
 480             }
 481             break;
 482         case TIFFTag.TIFF_RATIONAL:
 483             isDataArrayCorrect = data instanceof long[][]
 484                 && ((long[][])data).length == count;
 485             if (isDataArrayCorrect) {
 486                 for (long[] datum : (long[][])data) {
 487                     if (datum.length != 2) {
 488                         isDataArrayCorrect = false;
 489                         break;
 490                     }
 491                     if (datum[0] < 0 || datum[1] < 0) {
 492                         throw new IllegalArgumentException
 493                             ("Negative value supplied for TIFF_RATIONAL");
 494                     }
 495                     if (datum[0] > MAX_UINT32 || datum[1] > MAX_UINT32) {
 496                         throw new IllegalArgumentException
 497                             ("Too large value supplied for TIFF_RATIONAL");
 498                     }
 499                 }
 500             }
 501             break;
 502         case TIFFTag.TIFF_SSHORT:
 503             isDataArrayCorrect = data instanceof short[]
 504                 && ((short[])data).length == count;
 505             break;
 506         case TIFFTag.TIFF_SLONG:
 507             isDataArrayCorrect = data instanceof int[]
 508                 && ((int[])data).length == count;
 509             break;
 510         case TIFFTag.TIFF_SRATIONAL:
 511             isDataArrayCorrect = data instanceof int[][]
 512                 && ((int[][])data).length == count;
 513             if (isDataArrayCorrect) {
 514                 for (int[] datum : (int[][])data) {
 515                     if (datum.length != 2) {
 516                         isDataArrayCorrect = false;
 517                         break;
 518                     }
 519                 }
 520             }
 521             break;
 522         case TIFFTag.TIFF_FLOAT:
 523             isDataArrayCorrect = data instanceof float[]
 524                 && ((float[])data).length == count;
 525             break;
 526         case TIFFTag.TIFF_DOUBLE:
 527             isDataArrayCorrect = data instanceof double[]
 528                 && ((double[])data).length == count;
 529             break;
 530         default:
 531             throw new IllegalArgumentException("Unknown data type "+type);
 532         }
 533 
 534         if (!isDataArrayCorrect) {
 535             throw new IllegalArgumentException
 536                 ("Illegal class or length for data array");
 537         }
 538 
 539         this.tag = tag;
 540         this.tagNumber = tag.getNumber();
 541         this.type = type;
 542         this.count = count;
 543         this.data = data;
 544     }
 545 
 546     /**
 547      * Constructs a data array using {@link #createArrayForType
 548      * createArrayForType()} and invokes
 549      * {@link #TIFFField(TIFFTag,int,int,Object)} with the supplied
 550      * parameters and the created array.
 551      *
 552      * @param tag The tag to associated with this field.
 553      * @param type One of the {@code TIFFTag.TIFF_*} constants
 554      * indicating the data type of the field as written to the TIFF stream.
 555      * @param count The number of data values.
 556      * @throws NullPointerException if {@code tag == null}.
 557      * @throws IllegalArgumentException if {@code type} is not
 558      * one of the {@code TIFFTag.TIFF_*} data type constants.
 559      * @throws IllegalArgumentException if {@code type} is an unacceptable
 560      * data type for the supplied {@code TIFFTag}.
 561      * @throws IllegalArgumentException if {@code count < 0}.
 562      * @see #TIFFField(TIFFTag,int,int,Object)
 563      * @throws IllegalArgumentException if {@code count < 1}
 564      * and {@code type} is {@code TIFF_RATIONAL} or
 565      * {@code TIFF_SRATIONAL}.
 566      * @throws IllegalArgumentException if {@code count != 1}
 567      * and {@code type} is {@code TIFF_IFD_POINTER}.
 568      */
 569     public TIFFField(TIFFTag tag, int type, int count) {
 570         this(tag, type, count, createArrayForType(type, count));
 571     }
 572 
 573     /**
 574      * Constructs a {@code TIFFField} with a single non-negative integral
 575      * value. The field will have type {@link TIFFTag#TIFF_SHORT TIFF_SHORT}
 576      * if {@code value} is in {@code [0,0xffff]}, and type
 577      * {@link TIFFTag#TIFF_LONG TIFF_LONG} if {@code value} is in
 578      * {@code [0x10000,0xffffffff]}. The count of the field will be unity.
 579      *
 580      * @param tag The tag to associate with this field.
 581      * @param value The value to associate with this field.
 582      * @throws NullPointerException if {@code tag == null}.
 583      * @throws IllegalArgumentException if {@code value} is not in
 584      * {@code [0,0xffffffff]}.
 585      * @throws IllegalArgumentException if {@code value} is in
 586      * {@code [0,0xffff]} and {@code TIFF_SHORT} is an unacceptable type
 587      * for the {@code TIFFTag}, or if {@code value} is in
 588      * {@code [0x10000,0xffffffff]} and {@code TIFF_LONG} is an unacceptable
 589      * type for the {@code TIFFTag}.
 590      */
 591     public TIFFField(TIFFTag tag, long value) {
 592         if(tag == null) {
 593             throw new NullPointerException("tag == null!");
 594         }
 595         if (value < 0) {
 596             throw new IllegalArgumentException("value < 0!");
 597         }
 598         if (value > MAX_UINT32) {
 599             throw new IllegalArgumentException("value > 0xffffffff!");
 600         }
 601 
 602         this.tag = tag;
 603         this.tagNumber = tag.getNumber();
 604         this.count = 1;
 605 
 606         if (value < 65536) {
 607             if (!tag.isDataTypeOK(TIFFTag.TIFF_SHORT)) {
 608                 throw new IllegalArgumentException("Illegal data type "
 609                     + getTypeName(TIFFTag.TIFF_SHORT) + " for tag "
 610                     + "\"" + tag.getName() + "\"");
 611             }
 612             this.type = TIFFTag.TIFF_SHORT;
 613             char[] cdata = new char[1];
 614             cdata[0] = (char)value;
 615             this.data = cdata;
 616         } else {
 617             if (!tag.isDataTypeOK(TIFFTag.TIFF_LONG)) {
 618                 throw new IllegalArgumentException("Illegal data type "
 619                     + getTypeName(TIFFTag.TIFF_LONG) + " for tag "
 620                     + "\"" + tag.getName() + "\"");
 621             }
 622             this.type = TIFFTag.TIFF_LONG;
 623             long[] ldata = new long[1];
 624             ldata[0] = value;
 625             this.data = ldata;
 626         }
 627     }
 628 
 629     /**
 630      * Constructs a {@code TIFFField} with an IFD offset and contents.
 631      * The offset will be stored as the data of this field as
 632      * {@code long[] {offset}}. The directory will not be cloned. The count
 633      * of the field will be unity.
 634      *
 635      * @param tag The tag to associated with this field.
 636      * @param type One of the constants {@code TIFFTag.TIFF_LONG} or
 637      * {@code TIFFTag.TIFF_IFD_POINTER}.
 638      * @param offset The IFD offset.
 639      * @param dir The directory.
 640      *
 641      * @throws NullPointerException if {@code tag == null}.
 642      * @throws IllegalArgumentException if {@code type} is an unacceptable
 643      * data type for the supplied {@code TIFFTag}.
 644      * @throws IllegalArgumentException if {@code type} is neither
 645      * {@code TIFFTag.TIFF_LONG} nor {@code TIFFTag.TIFF_IFD_POINTER}.
 646      * @throws IllegalArgumentException if {@code offset <= 0}.
 647      * @throws NullPointerException if {@code dir == null}.
 648      *
 649      * @see #TIFFField(TIFFTag,int,int,Object)
 650      */
 651     public TIFFField(TIFFTag tag, int type, long offset, TIFFDirectory dir) {
 652         if (tag == null) {
 653             throw new NullPointerException("tag == null!");
 654         } else if (type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) {
 655             throw new IllegalArgumentException("Unknown data type "+type);
 656         } else if (!tag.isDataTypeOK(type)) {
 657             throw new IllegalArgumentException("Illegal data type " + type
 658                 + " for " + tag.getName() + " tag");
 659         } else if (type != TIFFTag.TIFF_LONG
 660                    && type != TIFFTag.TIFF_IFD_POINTER) {
 661             throw new IllegalArgumentException("type " + type
 662                 + " is neither TIFFTag.TIFF_LONG nor TIFFTag.TIFF_IFD_POINTER");
 663         } else if (offset <= 0) {
 664             throw new IllegalArgumentException("offset " + offset
 665                 + " is non-positive");
 666         } else if (dir == null) {
 667             throw new NullPointerException("dir == null");
 668         }
 669 
 670         this.tag = tag;
 671         this.tagNumber = tag.getNumber();
 672         this.type = type;
 673         this.count = 1;
 674         this.data = new long[] {offset};
 675 
 676         this.dir = dir;
 677     }
 678 
 679     /**
 680      * Retrieves the tag associated with this field.
 681      *
 682      * @return The associated {@code TIFFTag}.
 683      */
 684     public TIFFTag getTag() {
 685         return tag;
 686     }
 687 
 688     /**
 689      * Retrieves the tag number in the range {@code [0,65535]}.
 690      *
 691      * @return The tag number.
 692      */
 693     public int getTagNumber() {
 694         return tagNumber;
 695     }
 696 
 697     /**
 698      * Returns the type of the data stored in the field.  For a TIFF 6.0
 699      * stream, the value will equal one of the {@code TIFFTag.TIFF_*}
 700      * constants. For future revisions of TIFF, higher values are possible.
 701      *
 702      * @return The data type of the field value.
 703      */
 704     public int getType() {
 705         return type;
 706     }
 707 
 708     /**
 709      * Returns the name of the supplied data type constant.
 710      *
 711      * @param dataType One of the {@code TIFFTag.TIFF_*} constants
 712      * indicating the data type of the field as written to the TIFF stream.
 713      * @return The type name corresponding to the supplied type constant.
 714      * @throws IllegalArgumentException if {@code dataType} is not
 715      * one of the {@code TIFFTag.TIFF_*} data type constants.
 716      */
 717     public static String getTypeName(int dataType) {
 718         if (dataType < TIFFTag.MIN_DATATYPE ||
 719             dataType > TIFFTag.MAX_DATATYPE) {
 720             throw new IllegalArgumentException("Unknown data type "+dataType);
 721         }
 722 
 723         return TYPE_NAMES[dataType];
 724     }
 725 
 726     /**
 727      * Returns the data type constant corresponding to the supplied data
 728      * type name. If the name is unknown {@code -1} will be returned.
 729      *
 730      * @param typeName The type name.
 731      * @return One of the {@code TIFFTag.TIFF_*} constants or
 732      * {@code -1} if the name is not recognized.
 733      */
 734     public static int getTypeByName(String typeName) {
 735         for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
 736             if (typeName.equals(TYPE_NAMES[i])) {
 737                 return i;
 738             }
 739         }
 740 
 741         return -1;
 742     }
 743 
 744     /**
 745      * Creates an array appropriate for the indicated data type.
 746      *
 747      * @param dataType One of the {@code TIFFTag.TIFF_*} data type
 748      * constants.
 749      * @param count The number of values in the array.
 750      * @return An array appropriate for the specified data type.
 751      *
 752      * @throws IllegalArgumentException if {@code dataType} is not
 753      * one of the {@code TIFFTag.TIFF_*} data type constants.
 754      * @throws IllegalArgumentException if {@code count < 0}.
 755      * @throws IllegalArgumentException if {@code count < 1}
 756      * and {@code type} is {@code TIFF_RATIONAL} or
 757      * {@code TIFF_SRATIONAL}.
 758      * @throws IllegalArgumentException if {@code count != 1}
 759      * and {@code type} is {@code TIFF_IFD_POINTER}.
 760      */
 761     public static Object createArrayForType(int dataType, int count) {
 762 
 763         if(count < 0) {
 764             throw new IllegalArgumentException("count < 0!");
 765         } else if ((dataType == TIFFTag.TIFF_RATIONAL
 766                    || dataType == TIFFTag.TIFF_SRATIONAL)
 767                   && count < 1) {
 768             throw new IllegalArgumentException
 769                 ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1");
 770         } else if (dataType == TIFFTag.TIFF_IFD_POINTER && count != 1) {
 771             throw new IllegalArgumentException
 772                 ("Type is TIFF_IFD_POINTER and count != 1");
 773         }
 774 
 775         switch (dataType) {
 776         case TIFFTag.TIFF_BYTE:
 777         case TIFFTag.TIFF_SBYTE:
 778         case TIFFTag.TIFF_UNDEFINED:
 779             return new byte[count];
 780         case TIFFTag.TIFF_ASCII:
 781             return new String[count];
 782         case TIFFTag.TIFF_SHORT:
 783             return new char[count];
 784         case TIFFTag.TIFF_LONG:
 785         case TIFFTag.TIFF_IFD_POINTER:
 786             return new long[count];
 787         case TIFFTag.TIFF_RATIONAL:
 788             return new long[count][2];
 789         case TIFFTag.TIFF_SSHORT:
 790             return new short[count];
 791         case TIFFTag.TIFF_SLONG:
 792             return new int[count];
 793         case TIFFTag.TIFF_SRATIONAL:
 794             return new int[count][2];
 795         case TIFFTag.TIFF_FLOAT:
 796             return new float[count];
 797         case TIFFTag.TIFF_DOUBLE:
 798             return new double[count];
 799         default:
 800             throw new IllegalArgumentException("Unknown data type "+dataType);
 801         }
 802     }
 803 
 804     /**
 805      * Returns the {@code TIFFField} as a node named either
 806      * {@code "TIFFField"} or {@code "TIFFIFD"} as described in the
 807      * TIFF native image metadata specification. The node will be named
 808      * {@code "TIFFIFD"} if and only if {@link #hasDirectory()} returns
 809      * {@code true} and the field's type is either {@link TIFFTag#TIFF_LONG}
 810      * or {@link TIFFTag#TIFF_IFD_POINTER}.
 811      *
 812      * @return a {@code Node} named {@code "TIFFField"} or
 813      * {@code "TIFFIFD"}.
 814      */
 815     public Node getAsNativeNode() {
 816         return new TIFFFieldNode(this);
 817     }
 818 
 819     /**
 820      * Indicates whether the value associated with the field is of
 821      * integral data type.
 822      *
 823      * @return Whether the field type is integral.
 824      */
 825     public boolean isIntegral() {
 826         return IS_INTEGRAL[type];
 827     }
 828 
 829     /**
 830      * Returns the number of data items present in the field.  For
 831      * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the
 832      * number of {@code String}s, not the total length of the
 833      * data as in the file representation.
 834      *
 835      * @return The number of data items present in the field.
 836      */
 837     public int getCount() {
 838         return count;
 839     }
 840 
 841     /**
 842      * Returns a reference to the data object associated with the field.
 843      *
 844      * @return The data object of the field.
 845      */
 846     public Object getData() {
 847         return data;
 848     }
 849 
 850     /**
 851      * Returns the data as an uninterpreted array of
 852      * {@code byte}s.  The type of the field must be one of
 853      * {@code TIFFTag.TIFF_BYTE}, {@code TIFF_SBYTE}, or
 854      * {@code TIFF_UNDEFINED}.
 855      *
 856      * <p> For data in {@code TIFFTag.TIFF_BYTE} format, the application
 857      * must take care when promoting the data to longer integral types
 858      * to avoid sign extension.
 859      *
 860      * @throws ClassCastException if the field is not of type
 861      * {@code TIFF_BYTE}, {@code TIFF_SBYTE}, or
 862      * {@code TIFF_UNDEFINED}.
 863      * @return The data as an uninterpreted array of bytes.
 864      */
 865     public byte[] getAsBytes() {
 866         return (byte[])data;
 867     }
 868 
 869     /**
 870      * Returns {@code TIFFTag.TIFF_SHORT} data as an array of
 871      * {@code char}s (unsigned 16-bit integers).
 872      *
 873      * @throws ClassCastException if the field is not of type
 874      * {@code TIFF_SHORT}.
 875      * @return The data as an array of {@code char}s.
 876      */
 877     public char[] getAsChars() {
 878         return (char[])data;
 879     }
 880 
 881     /**
 882      * Returns {@code TIFFTag.TIFF_SSHORT} data as an array of
 883      * {@code short}s (signed 16-bit integers).
 884      *
 885      * @throws ClassCastException if the field is not of type
 886      * {@code TIFF_SSHORT}.
 887      * @return The data as an array of {@code short}s.
 888      */
 889     public short[] getAsShorts() {
 890         return (short[])data;
 891     }
 892 
 893     /**
 894      * Returns {@code TIFFTag.TIFF_SLONG} data as an array of
 895      * {@code int}s (signed 32-bit integers).
 896      *
 897      * @throws ClassCastException if the field is not of type
 898      * {@code TIFF_SHORT}, {@code TIFF_SSHORT}, or
 899      * {@code TIFF_SLONG}.
 900      * @return The data as an array of {@code int}s.
 901      */
 902     public int[] getAsInts() {
 903         if (data instanceof int[]) {
 904             return (int[])data;
 905         } else if (data instanceof char[]){
 906             char[] cdata = (char[])data;
 907             int[] idata = new int[cdata.length];
 908             for (int i = 0; i < cdata.length; i++) {
 909                 idata[i] = cdata[i] & 0xffff;
 910             }
 911             return idata;
 912         } else if (data instanceof short[]){
 913             short[] sdata = (short[])data;
 914             int[] idata = new int[sdata.length];
 915             for (int i = 0; i < sdata.length; i++) {
 916                 idata[i] = (int)sdata[i];
 917             }
 918             return idata;
 919         } else {
 920             throw new ClassCastException("Data not char[], short[], or int[]!");
 921         }
 922     }
 923 
 924     /**
 925      * Returns {@code TIFFTag.TIFF_LONG} or
 926      * {@code TIFF_IFD_POINTER} data as an array of
 927      * {@code long}s (signed 64-bit integers).
 928      *
 929      * @throws ClassCastException if the field is not of type
 930      * {@code TIFF_LONG} or {@code TIFF_IFD_POINTER}.
 931      * @return The data as an array of {@code long}s.
 932      */
 933     public long[] getAsLongs() {
 934         return (long[])data;
 935     }
 936 
 937     /**
 938      * Returns {@code TIFFTag.TIFF_FLOAT} data as an array of
 939      * {@code float}s (32-bit floating-point values).
 940      *
 941      * @throws ClassCastException if the field is not of type
 942      * {@code TIFF_FLOAT}.
 943      * @return The data as an array of {@code float}s.
 944      */
 945     public float[] getAsFloats() {
 946         return (float[])data;
 947     }
 948 
 949     /**
 950      * Returns {@code TIFFTag.TIFF_DOUBLE} data as an array of
 951      * {@code double}s (64-bit floating-point values).
 952      *
 953      * @throws ClassCastException if the field is not of type
 954      * {@code TIFF_DOUBLE}.
 955      * @return The data as an array of {@code double}s.
 956      */
 957     public double[] getAsDoubles() {
 958         return (double[])data;
 959     }
 960 
 961     /**
 962      * Returns {@code TIFFTag.TIFF_SRATIONAL} data as an array of
 963      * 2-element arrays of {@code int}s.
 964      *
 965      * @throws ClassCastException if the field is not of type
 966      * {@code TIFF_SRATIONAL}.
 967      * @return The data as an array of signed rationals.
 968      */
 969     public int[][] getAsSRationals() {
 970         return (int[][])data;
 971     }
 972 
 973     /**
 974      * Returns {@code TIFFTag.TIFF_RATIONAL} data as an array of
 975      * 2-element arrays of {@code long}s.
 976      *
 977      * @throws ClassCastException if the field is not of type
 978      * {@code TIFF_RATIONAL}.
 979      * @return The data as an array of unsigned rationals.
 980      */
 981     public long[][] getAsRationals() {
 982         return (long[][])data;
 983     }
 984 
 985     /**
 986      * Returns data in any format as an {@code int}.
 987      *
 988      * <p> {@code TIFFTag.TIFF_BYTE} values are treated as unsigned; that
 989      * is, no sign extension will take place and the returned value
 990      * will be in the range [0, 255].  {@code TIFF_SBYTE} data
 991      * will be returned in the range [-128, 127].
 992      *
 993      * <p> A {@code TIFF_UNDEFINED} value is treated as though
 994      * it were a {@code TIFF_BYTE}.
 995      *
 996      * <p> Data in {@code TIFF_SLONG}, {@code TIFF_LONG},
 997      * {@code TIFF_FLOAT}, {@code TIFF_DOUBLE} or
 998      * {@code TIFF_IFD_POINTER} format are simply cast to
 999      * {@code int} and may suffer from truncation.
1000      *
1001      * <p> Data in {@code TIFF_SRATIONAL} or
1002      * {@code TIFF_RATIONAL} format are evaluated by dividing the
1003      * numerator into the denominator using double-precision
1004      * arithmetic and then casting to {@code int}.  Loss of
1005      * precision and truncation may occur.
1006      *
1007      * <p> Data in {@code TIFF_ASCII} format will be parsed as by
1008      * the {@code Double.parseDouble} method, with the result
1009      * case to {@code int}.
1010      *
1011      * @param index The index of the data.
1012      * @return The data at the given index as an {@code int}.
1013      */
1014     public int getAsInt(int index) {
1015         switch (type) {
1016         case TIFFTag.TIFF_BYTE:
1017         case TIFFTag.TIFF_UNDEFINED:
1018             return ((byte[])data)[index] & 0xff;
1019         case TIFFTag.TIFF_SBYTE:
1020             return ((byte[])data)[index];
1021         case TIFFTag.TIFF_SHORT:
1022             return ((char[])data)[index] & 0xffff;
1023         case TIFFTag.TIFF_SSHORT:
1024             return ((short[])data)[index];
1025         case TIFFTag.TIFF_SLONG:
1026             return ((int[])data)[index];
1027         case TIFFTag.TIFF_LONG:
1028         case TIFFTag.TIFF_IFD_POINTER:
1029             return (int)((long[])data)[index];
1030         case TIFFTag.TIFF_FLOAT:
1031             return (int)((float[])data)[index];
1032         case TIFFTag.TIFF_DOUBLE:
1033             return (int)((double[])data)[index];
1034         case TIFFTag.TIFF_SRATIONAL:
1035             int[] ivalue = getAsSRational(index);
1036             return (int)((double)ivalue[0]/ivalue[1]);
1037         case TIFFTag.TIFF_RATIONAL:
1038             long[] lvalue = getAsRational(index);
1039             return (int)((double)lvalue[0]/lvalue[1]);
1040         case TIFFTag.TIFF_ASCII:
1041              String s = ((String[])data)[index];
1042              return (int)Double.parseDouble(s);
1043         default:
1044             throw new ClassCastException(); // should never happen
1045         }
1046     }
1047 
1048     /**
1049      * Returns data in any format as a {@code long}.
1050      *
1051      * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data
1052      * are treated as unsigned; that is, no sign extension will take
1053      * place and the returned value will be in the range [0, 255].
1054      * {@code TIFF_SBYTE} data will be returned in the range
1055      * [-128, 127].
1056      *
1057      * <p> Data in {@code TIFF_FLOAT} and {@code TIFF_DOUBLE} are
1058      * simply cast to {@code long} and may suffer from truncation.
1059      *
1060      * <p> Data in {@code TIFF_SRATIONAL} or
1061      * {@code TIFF_RATIONAL} format are evaluated by dividing the
1062      * numerator into the denominator using double-precision
1063      * arithmetic and then casting to {@code long}.  Loss of
1064      * precision and truncation may occur.
1065      *
1066      * <p> Data in {@code TIFF_ASCII} format will be parsed as by
1067      * the {@code Double.parseDouble} method, with the result
1068      * cast to {@code long}.
1069      *
1070      * @param index The index of the data.
1071      * @return The data at the given index as a {@code long}.
1072      */
1073     public long getAsLong(int index) {
1074         switch (type) {
1075         case TIFFTag.TIFF_BYTE:
1076         case TIFFTag.TIFF_UNDEFINED:
1077             return ((byte[])data)[index] & 0xff;
1078         case TIFFTag.TIFF_SBYTE:
1079             return ((byte[])data)[index];
1080         case TIFFTag.TIFF_SHORT:
1081             return ((char[])data)[index] & 0xffff;
1082         case TIFFTag.TIFF_SSHORT:
1083             return ((short[])data)[index];
1084         case TIFFTag.TIFF_SLONG:
1085             return ((int[])data)[index];
1086         case TIFFTag.TIFF_LONG:
1087         case TIFFTag.TIFF_IFD_POINTER:
1088             return ((long[])data)[index];
1089         case TIFFTag.TIFF_FLOAT:
1090             return (long)((float[])data)[index];
1091         case TIFFTag.TIFF_DOUBLE:
1092             return (long)((double[])data)[index];
1093         case TIFFTag.TIFF_SRATIONAL:
1094             int[] ivalue = getAsSRational(index);
1095             return (long)((double)ivalue[0]/ivalue[1]);
1096         case TIFFTag.TIFF_RATIONAL:
1097             long[] lvalue = getAsRational(index);
1098             return (long)((double)lvalue[0]/lvalue[1]);
1099         case TIFFTag.TIFF_ASCII:
1100              String s = ((String[])data)[index];
1101              return (long)Double.parseDouble(s);
1102         default:
1103             throw new ClassCastException(); // should never happen
1104         }
1105     }
1106 
1107     /**
1108      * Returns data in any format as a {@code float}.
1109      *
1110      * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data
1111      * are treated as unsigned; that is, no sign extension will take
1112      * place and the returned value will be in the range [0, 255].
1113      * {@code TIFF_SBYTE} data will be returned in the range
1114      * [-128, 127].
1115      *
1116      * <p> Data in {@code TIFF_SLONG}, {@code TIFF_LONG},
1117      * {@code TIFF_DOUBLE}, or {@code TIFF_IFD_POINTER} format are
1118      * simply cast to {@code float} and may suffer from
1119      * truncation.
1120      *
1121      * <p> Data in {@code TIFF_SRATIONAL} or
1122      * {@code TIFF_RATIONAL} format are evaluated by dividing the
1123      * numerator into the denominator using double-precision
1124      * arithmetic and then casting to {@code float}.
1125      *
1126      * <p> Data in {@code TIFF_ASCII} format will be parsed as by
1127      * the {@code Double.parseDouble} method, with the result
1128      * cast to {@code float}.
1129      *
1130      * @param index The index of the data.
1131      * @return The data at the given index as a {@code float}.
1132      */
1133     public float getAsFloat(int index) {
1134         switch (type) {
1135         case TIFFTag.TIFF_BYTE:
1136         case TIFFTag.TIFF_UNDEFINED:
1137             return ((byte[])data)[index] & 0xff;
1138         case TIFFTag.TIFF_SBYTE:
1139             return ((byte[])data)[index];
1140         case TIFFTag.TIFF_SHORT:
1141             return ((char[])data)[index] & 0xffff;
1142         case TIFFTag.TIFF_SSHORT:
1143             return ((short[])data)[index];
1144         case TIFFTag.TIFF_SLONG:
1145             return ((int[])data)[index];
1146         case TIFFTag.TIFF_LONG:
1147         case TIFFTag.TIFF_IFD_POINTER:
1148             return ((long[])data)[index];
1149         case TIFFTag.TIFF_FLOAT:
1150             return ((float[])data)[index];
1151         case TIFFTag.TIFF_DOUBLE:
1152             return (float)((double[])data)[index];
1153         case TIFFTag.TIFF_SRATIONAL:
1154             int[] ivalue = getAsSRational(index);
1155             return (float)((double)ivalue[0]/ivalue[1]);
1156         case TIFFTag.TIFF_RATIONAL:
1157             long[] lvalue = getAsRational(index);
1158             return (float)((double)lvalue[0]/lvalue[1]);
1159         case TIFFTag.TIFF_ASCII:
1160              String s = ((String[])data)[index];
1161              return (float)Double.parseDouble(s);
1162         default:
1163             throw new ClassCastException(); // should never happen
1164         }
1165     }
1166 
1167     /**
1168      * Returns data in any format as a {@code double}.
1169      *
1170      * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data
1171      * are treated as unsigned; that is, no sign extension will take
1172      * place and the returned value will be in the range [0, 255].
1173      * {@code TIFF_SBYTE} data will be returned in the range
1174      * [-128, 127].
1175      *
1176      * <p> Data in {@code TIFF_SRATIONAL} or
1177      * {@code TIFF_RATIONAL} format are evaluated by dividing the
1178      * numerator into the denominator using double-precision
1179      * arithmetic.
1180      *
1181      * <p> Data in {@code TIFF_ASCII} format will be parsed as by
1182      * the {@code Double.parseDouble} method.
1183      *
1184      * @param index The index of the data.
1185      * @return The data at the given index as a {@code double}.
1186      */
1187     public double getAsDouble(int index) {
1188         switch (type) {
1189         case TIFFTag.TIFF_BYTE:
1190         case TIFFTag.TIFF_UNDEFINED:
1191             return ((byte[])data)[index] & 0xff;
1192         case TIFFTag.TIFF_SBYTE:
1193             return ((byte[])data)[index];
1194         case TIFFTag.TIFF_SHORT:
1195             return ((char[])data)[index] & 0xffff;
1196         case TIFFTag.TIFF_SSHORT:
1197             return ((short[])data)[index];
1198         case TIFFTag.TIFF_SLONG:
1199             return ((int[])data)[index];
1200         case TIFFTag.TIFF_LONG:
1201         case TIFFTag.TIFF_IFD_POINTER:
1202             return ((long[])data)[index];
1203         case TIFFTag.TIFF_FLOAT:
1204             return ((float[])data)[index];
1205         case TIFFTag.TIFF_DOUBLE:
1206             return ((double[])data)[index];
1207         case TIFFTag.TIFF_SRATIONAL:
1208             int[] ivalue = getAsSRational(index);
1209             return (double)ivalue[0]/ivalue[1];
1210         case TIFFTag.TIFF_RATIONAL:
1211             long[] lvalue = getAsRational(index);
1212             return (double)lvalue[0]/lvalue[1];
1213         case TIFFTag.TIFF_ASCII:
1214              String s = ((String[])data)[index];
1215              return Double.parseDouble(s);
1216         default:
1217             throw new ClassCastException(); // should never happen
1218         }
1219     }
1220 
1221     /**
1222      * Returns a {@code TIFFTag.TIFF_ASCII} value as a
1223      * {@code String}.
1224      *
1225      * @throws ClassCastException if the field is not of type
1226      * {@code TIFF_ASCII}.
1227      *
1228      * @param index The index of the data.
1229      * @return The data at the given index as a {@code String}.
1230      */
1231     public String getAsString(int index) {
1232         return ((String[])data)[index];
1233     }
1234 
1235     /**
1236      * Returns a {@code TIFFTag.TIFF_SRATIONAL} data item as a
1237      * two-element array of {@code int}s.
1238      *
1239      * @param index The index of the data.
1240      * @return The data at the given index as a signed rational.
1241      * @throws ClassCastException if the field is not of type
1242      * {@code TIFF_SRATIONAL}.
1243      */
1244     public int[] getAsSRational(int index) {
1245         return ((int[][])data)[index];
1246     }
1247 
1248     /**
1249      * Returns a TIFFTag.TIFF_RATIONAL data item as a two-element array
1250      * of ints.
1251      *
1252      * @param index The index of the data.
1253      * @return The data at the given index as an unsigned rational.
1254      * @throws ClassCastException if the field is not of type
1255      * {@code TIFF_RATIONAL}.
1256      */
1257     public long[] getAsRational(int index) {
1258         return ((long[][])data)[index];
1259     }
1260 
1261 
1262     /**
1263      * Returns a {@code String} containing a human-readable
1264      * version of the data item.  Data of type
1265      * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} are
1266      * represented as a pair of integers separated by a
1267      * {@code '/'} character.  If the numerator of a
1268      * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} is an integral
1269      * multiple of the denominator, then the value is represented as
1270      * {@code "q/1"} where {@code q} is the quotient of the numerator and
1271      * denominator.
1272      *
1273      * @param index The index of the data.
1274      * @return The data at the given index as a {@code String}.
1275      * @throws ClassCastException if the field is not of one of the
1276      * legal field types.
1277      */
1278     public String getValueAsString(int index) {
1279         switch (type) {
1280         case TIFFTag.TIFF_ASCII:
1281             return ((String[])data)[index];
1282         case TIFFTag.TIFF_BYTE:
1283         case TIFFTag.TIFF_UNDEFINED:
1284             return Integer.toString(((byte[])data)[index] & 0xff);
1285         case TIFFTag.TIFF_SBYTE:
1286             return Integer.toString(((byte[])data)[index]);
1287         case TIFFTag.TIFF_SHORT:
1288             return Integer.toString(((char[])data)[index] & 0xffff);
1289         case TIFFTag.TIFF_SSHORT:
1290             return Integer.toString(((short[])data)[index]);
1291         case TIFFTag.TIFF_SLONG:
1292             return Integer.toString(((int[])data)[index]);
1293         case TIFFTag.TIFF_LONG:
1294         case TIFFTag.TIFF_IFD_POINTER:
1295             return Long.toString(((long[])data)[index]);
1296         case TIFFTag.TIFF_FLOAT:
1297             return Float.toString(((float[])data)[index]);
1298         case TIFFTag.TIFF_DOUBLE:
1299             return Double.toString(((double[])data)[index]);
1300         case TIFFTag.TIFF_SRATIONAL:
1301             int[] ivalue = getAsSRational(index);
1302             String srationalString;
1303             if(ivalue[1] != 0 && ivalue[0] % ivalue[1] == 0) {
1304                 // If the denominator is a non-zero integral divisor
1305                 // of the numerator then convert the fraction to be
1306                 // with respect to a unity denominator.
1307                 srationalString =
1308                     Integer.toString(ivalue[0] / ivalue[1]) + "/1";
1309             } else {
1310                 // Use the values directly.
1311                 srationalString =
1312                     Integer.toString(ivalue[0]) +
1313                     "/" +
1314                     Integer.toString(ivalue[1]);
1315             }
1316             return srationalString;
1317         case TIFFTag.TIFF_RATIONAL:
1318             long[] lvalue = getAsRational(index);
1319             String rationalString;
1320             if(lvalue[1] != 0L && lvalue[0] % lvalue[1] == 0) {
1321                 // If the denominator is a non-zero integral divisor
1322                 // of the numerator then convert the fraction to be
1323                 // with respect to a unity denominator.
1324                 rationalString =
1325                     Long.toString(lvalue[0] / lvalue[1]) + "/1";
1326             } else {
1327                 // Use the values directly.
1328                 rationalString =
1329                     Long.toString(lvalue[0]) +
1330                     "/" +
1331                     Long.toString(lvalue[1]);
1332             }
1333             return rationalString;
1334         default:
1335             throw new ClassCastException(); // should never happen
1336         }
1337     }
1338 
1339     /**
1340      * Returns whether the field has a {@code TIFFDirectory}.
1341      *
1342      * @return true if and only if getDirectory() returns non-null.
1343      */
1344     public boolean hasDirectory() {
1345         return getDirectory() != null;
1346     }
1347 
1348     /**
1349      * Returns the associated {@code TIFFDirectory}, if available. If no
1350      * directory is set, then {@code null} will be returned.
1351      *
1352      * @return the TIFFDirectory instance or null.
1353      */
1354     public TIFFDirectory getDirectory() {
1355         return dir;
1356     }
1357 
1358     /**
1359      * Clones the field and all the information contained therein.
1360      *
1361      * @return A clone of this {@code TIFFField}.
1362      * @throws CloneNotSupportedException if the instance cannot be cloned.
1363      */
1364     @Override
1365     public TIFFField clone() throws CloneNotSupportedException {
1366         TIFFField field = (TIFFField)super.clone();
1367 
1368         Object fieldData;
1369         switch (type) {
1370         case TIFFTag.TIFF_BYTE:
1371         case TIFFTag.TIFF_UNDEFINED:
1372         case TIFFTag.TIFF_SBYTE:
1373             fieldData = ((byte[])data).clone();
1374             break;
1375         case TIFFTag.TIFF_SHORT:
1376             fieldData = ((char[])data).clone();
1377             break;
1378         case TIFFTag.TIFF_SSHORT:
1379             fieldData = ((short[])data).clone();
1380             break;
1381         case TIFFTag.TIFF_SLONG:
1382             fieldData = ((int[])data).clone();
1383             break;
1384         case TIFFTag.TIFF_LONG:
1385         case TIFFTag.TIFF_IFD_POINTER:
1386             fieldData = ((long[])data).clone();
1387             break;
1388         case TIFFTag.TIFF_FLOAT:
1389             fieldData = ((float[])data).clone();
1390             break;
1391         case TIFFTag.TIFF_DOUBLE:
1392             fieldData = ((double[])data).clone();
1393             break;
1394         case TIFFTag.TIFF_SRATIONAL:
1395             fieldData = ((int[][])data).clone();
1396             break;
1397         case TIFFTag.TIFF_RATIONAL:
1398             fieldData = ((long[][])data).clone();
1399             break;
1400         case TIFFTag.TIFF_ASCII:
1401             fieldData = ((String[])data).clone();
1402             break;
1403         default:
1404             throw new ClassCastException(); // should never happen
1405         }
1406 
1407         field.tag = tag;
1408         field.tagNumber = tagNumber;
1409         field.type = type;
1410         field.count = count;
1411         field.data = fieldData;
1412         field.dir = dir != null ? dir.clone() : null;
1413 
1414         return field;
1415     }
1416 }