001/*
002 * $RCSfile: TIFFField.java,v $
003 *
004 * 
005 * Copyright (c) 2006 Sun Microsystems, Inc. All  Rights Reserved.
006 * 
007 * Redistribution and use in source and binary forms, with or without
008 * modification, are permitted provided that the following conditions
009 * are met: 
010 * 
011 * - Redistribution of source code must retain the above copyright 
012 *   notice, this  list of conditions and the following disclaimer.
013 * 
014 * - Redistribution in binary form must reproduce the above copyright
015 *   notice, this list of conditions and the following disclaimer in 
016 *   the documentation and/or other materials provided with the
017 *   distribution.
018 * 
019 * Neither the name of Sun Microsystems, Inc. or the names of 
020 * contributors may be used to endorse or promote products derived 
021 * from this software without specific prior written permission.
022 * 
023 * This software is provided "AS IS," without a warranty of any 
024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035 * POSSIBILITY OF SUCH DAMAGES. 
036 * 
037 * You acknowledge that this software is not designed or intended for 
038 * use in the design, construction, operation or maintenance of any 
039 * nuclear facility. 
040 *
041 * $Revision: 1.4 $
042 * $Date: 2006/04/28 01:28:49 $
043 * $State: Exp $
044 */
045package com.github.jaiimageio.plugins.tiff;
046
047import java.io.IOException;
048import java.io.Serializable;
049import java.util.StringTokenizer;
050
051import javax.imageio.metadata.IIOMetadataNode;
052import javax.imageio.stream.ImageOutputStream;
053
054import org.w3c.dom.NamedNodeMap;
055import org.w3c.dom.Node;
056
057import com.github.jaiimageio.impl.plugins.tiff.TIFFFieldNode;
058import com.github.jaiimageio.plugins.tiff.TIFFTag;
059import com.github.jaiimageio.plugins.tiff.TIFFTagSet;
060
061/**
062 * A class representing a field in a TIFF 6.0 Image File Directory.
063 *
064 * <p> A field in a TIFF Image File Directory (IFD) is defined as a
065 * tag number accompanied by a sequence of values of identical data type.
066 * TIFF 6.0 defines 12 data types; a 13th type <code>IFD</code> is
067 * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These
068 * TIFF data types are referred to by Java constants and mapped internally
069 * onto Java language data types and type names as follows:
070 *
071 * <br>
072 * <br>
073 * <table border="1">
074 *
075 * <tr>
076 * <th>
077 * <b>TIFF Data Type</b>
078 * </th>
079 * <th>
080 * <b>Java Constant</b>
081 * </th>
082 * <th>
083 * <b>Java Data Type</b>
084 * </th>
085 * <th>
086 * <b>Java Type Name</b>
087 * </th>
088 * </tr>
089 *
090 * <tr>
091 * <td>
092 * <tt>BYTE</tt>
093 * </td>
094 * <td>
095 * {@link TIFFTag#TIFF_BYTE}
096 * </td>
097 * <td>
098 * <code>byte</code>
099 * </td>
100 * <td>
101 * <code>"Byte"</code>
102 * </td>
103 * </tr>
104 *
105 * <tr>
106 * <td>
107 * <tt>ASCII</tt>
108 * </td>
109 * <td>
110 * {@link TIFFTag#TIFF_ASCII}
111 * </td>
112 * <td>
113 * <code>String</code>
114 * </td>
115 * <td>
116 * <code>"Ascii"</code>
117 * </td>
118 * </tr>
119 *
120 * <tr>
121 * <td>
122 * <tt>SHORT</tt>
123 * </td>
124 * <td>
125 * {@link TIFFTag#TIFF_SHORT}
126 * </td>
127 * <td>
128 * <code>char</code>
129 * </td>
130 * <td>
131 * <code>"Short"</code>
132 * </td>
133 * </tr>
134 *
135 * <tr>
136 * <td>
137 * <tt>LONG</tt>
138 * </td>
139 * <td>
140 * {@link TIFFTag#TIFF_LONG}
141 * </td>
142 * <td>
143 * <code>long</code>
144 * </td>
145 * <td>
146 * <code>"Long"</code>
147 * </td>
148 * </tr>
149 *
150 * <tr>
151 * <td>
152 * <tt>RATIONAL</tt>
153 * </td>
154 * <td>
155 * {@link TIFFTag#TIFF_RATIONAL}
156 * </td>
157 * <td>
158 * <code>long[2]</code> {numerator, denominator}
159 * </td>
160 * <td>
161 * <code>"Rational"</code>
162 * </td>
163 * </tr>
164 *
165 * <tr>
166 * <td>
167 * <tt>SBYTE</tt>
168 * </td>
169 * <td>
170 * {@link TIFFTag#TIFF_SBYTE}
171 * </td>
172 * <td>
173 * <code>byte</code>
174 * </td>
175 * <td>
176 * <code>"SByte"</code>
177 * </td>
178 * </tr>
179 *
180 * <tr>
181 * <td>
182 * <tt>UNDEFINED</tt>
183 * </td>
184 * <td>
185 * {@link TIFFTag#TIFF_UNDEFINED}
186 * </td>
187 * <td>
188 * <code>byte</code>
189 * </td>
190 * <td>
191 * <code>"Undefined"</code>
192 * </td>
193 * </tr>
194 *
195 * <tr>
196 * <td>
197 * <tt>SSHORT</tt>
198 * </td>
199 * <td>
200 * {@link TIFFTag#TIFF_SSHORT}
201 * </td>
202 * <td>
203 * <code>short</code>
204 * </td>
205 * <td>
206 * <code>"SShort"</code>
207 * </td>
208 * </tr>
209 *
210 * <tr>
211 * <td>
212 * <tt>SLONG</tt>
213 * </td>
214 * <td>
215 * {@link TIFFTag#TIFF_SLONG}
216 * </td>
217 * <td>
218 * <code>int</code>
219 * </td>
220 * <td>
221 * <code>"SLong"</code>
222 * </td>
223 * </tr>
224 *
225 * <tr>
226 * <td>
227 * <tt>SRATIONAL</tt>
228 * </td>
229 * <td>
230 * {@link TIFFTag#TIFF_SRATIONAL}
231 * </td>
232 * <td>
233 * <code>int[2]</code> {numerator, denominator}
234 * </td>
235 * <td>
236 * <code>"SRational"</code>
237 * </td>
238 * </tr>
239 *
240 * <tr>
241 * <td>
242 * <tt>FLOAT</tt>
243 * </td>
244 * <td>
245 * {@link TIFFTag#TIFF_FLOAT}
246 * </td>
247 * <td>
248 * <code>float</code>
249 * </td>
250 * <td>
251 * <code>"Float"</code>
252 * </td>
253 * </tr>
254 *
255 * <tr>
256 * <td>
257 * <tt>DOUBLE</tt>
258 * </td>
259 * <td>
260 * {@link TIFFTag#TIFF_DOUBLE}
261 * </td>
262 * <td>
263 * <code>double</code>
264 * </td>
265 * <td>
266 * <code>"Double"</code>
267 * </td>
268 * </tr>
269 *
270 * <tr>
271 * <td>
272 * <tt>IFD</tt>
273 * </td>
274 * <td>
275 * {@link TIFFTag#TIFF_IFD_POINTER}
276 * </td>
277 * <td>
278 * <code>long</code>
279 * </td>
280 * <td>
281 * <code>"IFDPointer"</code>
282 * </td>
283 * </tr>
284 *
285 * </table>
286 *
287 * @see TIFFDirectory
288 * @see TIFFTag
289 */
290public class TIFFField implements Comparable {
291
292    private static final String[] typeNames = {
293        null,
294        "Byte", "Ascii", "Short", "Long", "Rational",
295        "SByte", "Undefined", "SShort", "SLong", "SRational",
296        "Float", "Double", "IFDPointer"
297    };
298
299    private static final boolean[] isIntegral = {
300        false,
301        true, false, true, true, false,
302        true, true, true, true, false,
303        false, false, false
304    };
305
306    /** The tag. */
307    private TIFFTag tag;
308
309    /** The tag number. */
310    private int tagNumber;
311
312    /** The tag type. */
313    private int type;
314
315    /** The number of data items present in the field. */
316    private int count;
317
318    /** The field data. */
319    private Object data;
320    
321    /** The default constructor. */
322    private TIFFField() {}
323
324    private static String getAttribute(Node node, String attrName) {
325        NamedNodeMap attrs = node.getAttributes();
326        return attrs.getNamedItem(attrName).getNodeValue();
327    }
328
329    private static void initData(Node node,
330                                 int[] otype, int[] ocount, Object[] odata) {
331        int type;
332        int count;
333        Object data = null;
334
335        String typeName = node.getNodeName();
336        typeName = typeName.substring(4);
337        typeName = typeName.substring(0, typeName.length() - 1);
338        type = TIFFField.getTypeByName(typeName);
339        if (type == -1) {
340            throw new IllegalArgumentException("typeName = " + typeName);
341        }
342
343        Node child = node.getFirstChild();
344
345        count = 0;
346        while (child != null) {
347            String childTypeName = child.getNodeName().substring(4);
348            if (!typeName.equals(childTypeName)) {
349                // warning
350            }
351                            
352            ++count;
353            child = child.getNextSibling();
354        }
355                        
356        if (count > 0) {
357            data = createArrayForType(type, count);
358            child = node.getFirstChild();
359            int idx = 0;
360            while (child != null) {
361                String value = getAttribute(child, "value");
362                
363                String numerator, denominator;
364                int slashPos;
365                
366                switch (type) {
367                case TIFFTag.TIFF_ASCII:
368                    ((String[])data)[idx] = value;
369                    break;
370                case TIFFTag.TIFF_BYTE:
371                case TIFFTag.TIFF_SBYTE:
372                    ((byte[])data)[idx] =
373                        (byte)Integer.parseInt(value);
374                    break;
375                case TIFFTag.TIFF_SHORT:
376                    ((char[])data)[idx] =
377                        (char)Integer.parseInt(value);
378                    break;
379                case TIFFTag.TIFF_SSHORT:
380                    ((short[])data)[idx] =
381                        (short)Integer.parseInt(value);
382                    break;
383                case TIFFTag.TIFF_SLONG:
384                    ((int[])data)[idx] =
385                        (int)Integer.parseInt(value);
386                    break;
387                case TIFFTag.TIFF_LONG:
388                case TIFFTag.TIFF_IFD_POINTER:
389                    ((long[])data)[idx] =
390                        (long)Long.parseLong(value);
391                    break;
392                case TIFFTag.TIFF_FLOAT:
393                    ((float[])data)[idx] =
394                        (float)Float.parseFloat(value);
395                    break;
396                case TIFFTag.TIFF_DOUBLE:
397                    ((double[])data)[idx] =
398                        (double)Double.parseDouble(value);
399                    break;
400                case TIFFTag.TIFF_SRATIONAL:
401                    slashPos = value.indexOf("/");
402                    numerator = value.substring(0, slashPos);
403                    denominator = value.substring(slashPos + 1);
404                    
405                    ((int[][])data)[idx] = new int[2];
406                    ((int[][])data)[idx][0] =
407                        Integer.parseInt(numerator);
408                    ((int[][])data)[idx][1] =
409                        Integer.parseInt(denominator);
410                    break;
411                case TIFFTag.TIFF_RATIONAL:
412                    slashPos = value.indexOf("/");
413                    numerator = value.substring(0, slashPos);
414                    denominator = value.substring(slashPos + 1);
415                    
416                    ((long[][])data)[idx] = new long[2];
417                    ((long[][])data)[idx][0] =
418                        Long.parseLong(numerator);
419                    ((long[][])data)[idx][1] =
420                        Long.parseLong(denominator);
421                    break;
422                default:
423                    // error
424                }
425                
426                idx++;
427                child = child.getNextSibling();
428            }
429        }
430
431        otype[0] = type;
432        ocount[0] = count;
433        odata[0] = data;
434    }
435
436    /**
437     * Creates a <code>TIFFField</code> from a TIFF native image
438     * metadata node. If the value of the <tt>"tagNumber"</tt> attribute
439     * of the node is not found in <code>tagSet</code> then a new
440     * <code>TIFFTag</code> with name <code>"unknown"</code> will be
441     * created and assigned to the field.
442     *
443     * @param tagSet The <code>TIFFTagSet</code> to which the
444     * <code>TIFFTag</code> of the field belongs.
445     * @param node A native TIFF image metadata <code>TIFFField</code> node.
446     * @throws IllegalArgumentException if <code>node</code> is
447     * <code>null</code>.
448     * @throws IllegalArgumentException if the name of the node is not
449     * <code>"TIFFField"</code>.
450     */
451    public static TIFFField createFromMetadataNode(TIFFTagSet tagSet,
452                                                   Node node) {
453        if (node == null) {
454            throw new IllegalArgumentException("node == null!");
455        }
456        String name = node.getNodeName();
457        if (!name.equals("TIFFField")) {
458            throw new IllegalArgumentException("!name.equals(\"TIFFField\")");
459        }
460
461        int tagNumber = Integer.parseInt(getAttribute(node, "number"));
462        TIFFTag tag;
463        if (tagSet != null) {
464            tag = tagSet.getTag(tagNumber);
465        } else {
466            tag = new TIFFTag("unknown", tagNumber, 0, null);
467        }
468
469        int type = TIFFTag.TIFF_UNDEFINED;
470        int count = 0;
471        Object data = null;
472
473        Node child = node.getFirstChild();
474        if (child != null) {
475            String typeName = child.getNodeName();
476            if (typeName.equals("TIFFUndefined")) {
477                String values = getAttribute(child, "value");
478                StringTokenizer st = new StringTokenizer(values, ",");
479                count = st.countTokens();
480
481                byte[] bdata = new byte[count];
482                for (int i = 0; i < count; i++) {
483                    bdata[i] = (byte)Integer.parseInt(st.nextToken());
484                }
485
486                type = TIFFTag.TIFF_UNDEFINED;
487                data = bdata;
488            } else {
489                int[] otype = new int[1];
490                int[] ocount = new int[1];
491                Object[] odata = new Object[1];
492
493                initData(node.getFirstChild(), otype, ocount, odata); 
494                type = otype[0];
495                count = ocount[0];
496                data = odata[0];
497            }
498        } else {
499            int t = TIFFTag.MAX_DATATYPE;
500            while(t >= TIFFTag.MIN_DATATYPE && !tag.isDataTypeOK(t)) {
501                t--;
502            }
503            type = t;
504        }
505
506        return new TIFFField(tag, type, count, data);
507    }
508
509    /**
510     * Constructs a <code>TIFFField</code> with arbitrary data. The
511     * <code>type</code> parameter must be a value for which
512     * {@link TIFFTag#isDataTypeOK <code>tag.isDataTypeOK()</code>}
513     * returns <code>true</code>. The <code>data</code> parameter must
514     * be an array of a Java type appropriate for the type of the TIFF
515     * field unless {@link TIFFTag#isIFDPointer
516     * <code>tag.isIFDPointer()</code>} returns <code>true</code> in
517     * which case it must be a <code>TIFFDirectory</code> instance.
518     *
519     * <p><i>Neither the legality of <code>type</code> with respect to
520     * <code>tag</code> nor that or <code>data</code> with respect to
521     * <code>type</code> is verified by this constructor.</i> The methods
522     * {@link TIFFTag#isDataTypeOK <code>TIFFTag.isDataTypeOK()</code>}
523     * and {@link #createArrayForType <code>createArrayForType()</code>}
524     * should be used programmatically to ensure that subsequent errors
525     * such as <code>ClassCastException</code>s do not occur as a result
526     * of providing inconsitent parameters to this constructor.</p>
527     *
528     * <p>Note that the value (data) of the <code>TIFFField</code>
529     * will always be the actual field value regardless of the number of
530     * bytes required for that value. This is the case despite the fact
531     * that the TIFF <i>IFD Entry</i> corresponding to the field may
532     * actually contain the offset to the field's value rather than
533     * the value itself (the latter occurring if and only if the
534     * value fits into 4 bytes). In other words, the value of the
535     * field will already have been read from the TIFF stream. This
536     * subsumes the case where <code>tag.isIFDPointer()</code> returns
537     * <code>true</code> and the value will be a <code>TIFFDirectory</code>
538     * rather than an array.</p>
539     *
540     * @param tag The tag to associated with this field.
541     * @param type One of the <code>TIFFTag.TIFF_*</code> constants
542     * indicating the data type of the field as written to the TIFF stream.
543     * @param count The number of data values.
544     * @param data The actual data content of the field.
545     *
546     * @throws IllegalArgumentException if <code>tag&nbsp;==&nbsp;null</code>.
547     * @throws IllegalArgumentException if <code>dataType</code> is not
548     * one of the <code>TIFFTag.TIFF_*</code> data type constants.
549     * @throws IllegalArgumentException if <code>count&nbsp;&lt;&nbsp;0</code>.
550     */
551    public TIFFField(TIFFTag tag, int type, int count, Object data) {
552        if(tag == null) {
553            throw new IllegalArgumentException("tag == null!");
554        } else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) {
555            throw new IllegalArgumentException("Unknown data type "+type);
556        } else if(count < 0) {
557            throw new IllegalArgumentException("count < 0!");
558        }
559        this.tag = tag;
560        this.tagNumber = tag.getNumber();
561        this.type = type;
562        this.count = count;
563        this.data = data;
564    }
565
566    /**
567     * Constructs a data array using {@link #createArrayForType
568     * <code>createArrayForType()</code>} and invokes
569     * {@link #TIFFField(TIFFTag,int,int,Object)} with the supplied
570     * parameters and the created array.
571     *
572     * @see #TIFFField(TIFFTag,int,int,Object)
573     */
574    public TIFFField(TIFFTag tag, int type, int count) {
575        this(tag, type, count, createArrayForType(type, count));
576    }
577
578    /**
579     * Constructs a <code>TIFFField</code> with a single integral value.
580     * The field will have type
581     * {@link TIFFTag#TIFF_SHORT  <code>TIFF_SHORT</code>} if
582     * <code>val&nbsp;&lt;&nbsp;65536</code> and type
583     * {@link TIFFTag#TIFF_LONG <code>TIFF_LONG</code>} otherwise.
584     * <i>It is <b>not</b> verified whether the resulting type is
585     * legal for <code>tag</code>.</i>
586     *
587     * @param tag The tag to associate with this field.
588     * @param value The value to associate with this field.
589     * @throws IllegalArgumentException if <code>tag&nbsp;==&nbsp;null</code>.
590     * @throws IllegalArgumentException if <code>value&nbsp;&lt;&nbsp;0</code>.
591     */
592    public TIFFField(TIFFTag tag, int value) {
593        if(tag == null) {
594            throw new IllegalArgumentException("tag == null!");
595        }
596        if (value < 0) {
597            throw new IllegalArgumentException("value < 0!");
598        }
599
600        this.tag = tag;
601        this.tagNumber = tag.getNumber();
602        this.count = 1;
603
604        if (value < 65536) {
605            this.type = TIFFTag.TIFF_SHORT;
606            char[] cdata = new char[1];
607            cdata[0] = (char)value;
608            this.data = cdata;
609        } else {
610            this.type = TIFFTag.TIFF_LONG;
611            long[] ldata = new long[1];
612            ldata[0] = value;
613            this.data = ldata;
614        }
615    }
616
617    /**
618     * Retrieves the tag associated with this field.
619     *
620     * @return The associated <code>TIFFTag</code>.
621     */
622    public TIFFTag getTag() {
623        return tag;
624    }
625
626    /**
627     * Retrieves the tag number in the range <code>[0,&nbsp;65535]</code>.
628     *
629     * @return The tag number.
630     */
631    public int getTagNumber() {
632        return tagNumber;
633    }
634
635    /**
636     * Returns the type of the data stored in the field.  For a TIFF 6.0
637     * stream, the value will equal one of the <code>TIFFTag.TIFF_*</code>
638     * constants. For future revisions of TIFF, higher values are possible.
639     *
640     * @return The data type of the field value.
641     */
642    public int getType() {
643        return type;
644    }
645
646    /**
647     * Returns the name of the supplied data type constant.
648     *
649     * @param dataType One of the <code>TIFFTag.TIFF_*</code> constants
650     * indicating the data type of the field as written to the TIFF stream.
651     * @return The type name corresponding to the supplied type constant.
652     * @throws IllegalArgumentException if <code>dataType</code> is not
653     * one of the <code>TIFFTag.TIFF_*</code> data type constants.
654     */
655    public static String getTypeName(int dataType) {
656        if (dataType < TIFFTag.MIN_DATATYPE ||
657            dataType > TIFFTag.MAX_DATATYPE) {
658            throw new IllegalArgumentException("Unknown data type "+dataType);
659        }
660
661        return typeNames[dataType];
662    }
663
664    /**
665     * Returns the data type constant corresponding to the supplied data
666     * type name. If the name is unknown <code>-1</code> will be returned.
667     *
668     * @return One of the <code>TIFFTag.TIFF_*</code> constants or
669     * <code>-1</code> if the name is not recognized.
670     */
671    public static int getTypeByName(String typeName) {
672        for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
673            if (typeName.equals(typeNames[i])) {
674                return i;
675            }
676        }
677
678        return -1;
679    }
680
681    /**
682     * Creates an array appropriate for the indicated data type.
683     *
684     * @param dataType One of the <code>TIFFTag.TIFF_*</code> data type
685     * constants.
686     * @param count The number of values in the array.
687     *
688     * @throws IllegalArgumentException if <code>dataType</code> is not
689     * one of the <code>TIFFTag.TIFF_*</code> data type constants.
690     * @throws IllegalArgumentException if <code>count&nbsp;&lt;&nbsp;0</code>.
691     */
692    public static Object createArrayForType(int dataType, int count) {
693        if(count < 0) {
694            throw new IllegalArgumentException("count < 0!");
695        }
696        switch (dataType) {
697        case TIFFTag.TIFF_BYTE:
698        case TIFFTag.TIFF_SBYTE:
699        case TIFFTag.TIFF_UNDEFINED:
700            return new byte[count];
701        case TIFFTag.TIFF_ASCII:
702            return new String[count];
703        case TIFFTag.TIFF_SHORT:
704            return new char[count];
705        case TIFFTag.TIFF_LONG:
706        case TIFFTag.TIFF_IFD_POINTER:
707            return new long[count];
708        case TIFFTag.TIFF_RATIONAL:
709            return new long[count][2];
710        case TIFFTag.TIFF_SSHORT:
711            return new short[count];
712        case TIFFTag.TIFF_SLONG:
713            return new int[count];
714        case TIFFTag.TIFF_SRATIONAL:
715            return new int[count][2];
716        case TIFFTag.TIFF_FLOAT:
717            return new float[count];
718        case TIFFTag.TIFF_DOUBLE:
719            return new double[count];
720        default:
721            throw new IllegalArgumentException("Unknown data type "+dataType);
722        }
723    }
724
725    /**
726     * Returns the <code>TIFFField</code> as a node named either
727     * <tt>"TIFFField"</tt> or <tt>"TIFFIFD"</tt> as described in the
728     * TIFF native image metadata specification. The node will be named
729     * <tt>"TIFFIFD"</tt> if and only if the field's data object is an
730     * instance of {@link TIFFDirectory} or equivalently
731     * {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns
732     * <code>true</code>.
733     *
734     * @return a <code>Node</code> named <tt>"TIFFField"</tt> or
735     * <tt>"TIFFIFD"</tt>.
736     */
737    public Node getAsNativeNode() {
738        return new TIFFFieldNode(this);
739    }
740
741    /**
742     * Indicates whether the value associated with the field is of
743     * integral data type.
744     *
745     * @return Whether the field type is integral.
746     */
747    public boolean isIntegral() {
748        return isIntegral[type];
749    }
750
751    /**
752     * Returns the number of data items present in the field.  For
753     * <code>TIFFTag.TIFF_ASCII</code> fields, the value returned is the
754     * number of <code>String</code>s, not the total length of the
755     * data as in the file representation.
756     */
757    public int getCount() {
758        return count;
759    }
760
761    /**
762     * Returns a reference to the data object associated with the field.
763     *
764     * @return The data object of the field.
765     */
766    public Object getData() {
767        return data;
768    }
769
770    /**
771     * Returns the data as an uninterpreted array of
772     * <code>byte</code>s.  The type of the field must be one of
773     * <code>TIFFTag.TIFF_BYTE</code>, <code>TIFF_SBYTE</code>, or
774     * <code>TIFF_UNDEFINED</code>.
775     *
776     * <p> For data in <code>TIFFTag.TIFF_BYTE</code> format, the application
777     * must take care when promoting the data to longer integral types
778     * to avoid sign extension.
779     *
780     * @throws ClassCastException if the field is not of type
781     * <code>TIFF_BYTE</code>, <code>TIFF_SBYTE</code>, or
782     * <code>TIFF_UNDEFINED</code>.
783     */
784    public byte[] getAsBytes() {
785        return (byte[])data;
786    }
787
788    /**
789     * Returns <code>TIFFTag.TIFF_SHORT</code> data as an array of
790     * <code>char</code>s (unsigned 16-bit integers).
791     *
792     * @throws ClassCastException if the field is not of type
793     * <code>TIFF_SHORT</code>.
794     */
795    public char[] getAsChars() {
796        return (char[])data;
797    }
798
799    /**
800     * Returns <code>TIFFTag.TIFF_SSHORT</code> data as an array of
801     * <code>short</code>s (signed 16-bit integers).
802     *
803     * @throws ClassCastException if the field is not of type
804     * <code>TIFF_SSHORT</code>.
805     */
806    public short[] getAsShorts() {
807        return (short[])data;
808    }
809
810    /**
811     * Returns <code>TIFFTag.TIFF_SLONG</code> data as an array of
812     * <code>int</code>s (signed 32-bit integers).
813     *
814     * @throws ClassCastException if the field is not of type
815     * <code>TIFF_SHORT</code>, <code>TIFF_SSHORT</code>, or
816     * <code>TIFF_SLONG</code>.
817     */
818    public int[] getAsInts() {
819        if (data instanceof int[]) {
820            return (int[])data;
821        } else if (data instanceof char[]){
822            char[] cdata = (char[])data;
823            int[] idata = new int[cdata.length];
824            for (int i = 0; i < cdata.length; i++) {
825                idata[i] = (int)(cdata[i] & 0xffff);
826            }
827            return idata;
828        } else if (data instanceof short[]){
829            short[] sdata = (short[])data;
830            int[] idata = new int[sdata.length];
831            for (int i = 0; i < sdata.length; i++) {
832                idata[i] = (int)sdata[i];
833            }
834            return idata;
835        } else {
836            throw new ClassCastException(
837                                        "Data not char[], short[], or int[]!");
838        }
839    }
840
841    /**
842     * Returns <code>TIFFTag.TIFF_LONG</code> or
843     * <code>TIFF_IFD_POINTER</code> data as an array of
844     * <code>long</code>s (signed 64-bit integers).
845     *
846     * @throws ClassCastException if the field is not of type
847     * <code>TIFF_LONG</code> or <code>TIFF_IFD_POINTER</code>.
848     */
849    public long[] getAsLongs() {
850        return (long[])data;
851    }
852
853    /**
854     * Returns <code>TIFFTag.TIFF_FLOAT</code> data as an array of
855     * <code>float</code>s (32-bit floating-point values).
856     *
857     * @throws ClassCastException if the field is not of type
858     * <code>TIFF_FLOAT</code>.
859     */
860    public float[] getAsFloats() {
861        return (float[])data;
862    }
863
864    /**
865     * Returns <code>TIFFTag.TIFF_DOUBLE</code> data as an array of
866     * <code>double</code>s (64-bit floating-point values).
867     *
868     * @throws ClassCastException if the field is not of type
869     * <code>TIFF_DOUBLE</code>.
870     */
871    public double[] getAsDoubles() {
872        return (double[])data;
873    }
874
875    /**
876     * Returns <code>TIFFTag.TIFF_SRATIONAL</code> data as an array of
877     * 2-element arrays of <code>int</code>s.
878     *
879     * @throws ClassCastException if the field is not of type
880     * <code>TIFF_SRATIONAL</code>.
881     */
882    public int[][] getAsSRationals() {
883        return (int[][])data;
884    }
885
886    /**
887     * Returns <code>TIFFTag.TIFF_RATIONAL</code> data as an array of
888     * 2-element arrays of <code>long</code>s.
889     *
890     * @throws ClassCastException if the field is not of type
891     * <code>TIFF_RATIONAL</code>.
892     */
893    public long[][] getAsRationals() {
894        return (long[][])data;
895    }
896
897    /**
898     * Returns data in any format as an <code>int</code>.
899     *
900     * <p> <code>TIFFTag.TIFF_BYTE</code> values are treated as unsigned; that
901     * is, no sign extension will take place and the returned value
902     * will be in the range [0, 255].  <code>TIFF_SBYTE</code> data
903     * will be returned in the range [-128, 127].
904     *
905     * <p> A <code>TIFF_UNDEFINED</code> value is treated as though
906     * it were a <code>TIFF_BYTE</code>.
907     *
908     * <p> Data in <code>TIFF_SLONG</code>, <code>TIFF_LONG</code>,
909     * <code>TIFF_FLOAT</code>, <code>TIFF_DOUBLE</code> or
910     * <code>TIFF_IFD_POINTER</code> format are simply cast to
911     * <code>int</code> and may suffer from truncation.
912     *
913     * <p> Data in <code>TIFF_SRATIONAL</code> or
914     * <code>TIFF_RATIONAL</code> format are evaluated by dividing the
915     * numerator into the denominator using double-precision
916     * arithmetic and then casting to <code>int</code>.  Loss of
917     * precision and truncation may occur.
918     *
919     * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by
920     * the <code>Double.parseDouble</code> method, with the result
921     * case to <code>int</code>.
922     */
923    public int getAsInt(int index) {
924        switch (type) {
925        case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
926            return ((byte[])data)[index] & 0xff;
927        case TIFFTag.TIFF_SBYTE:
928            return ((byte[])data)[index];
929        case TIFFTag.TIFF_SHORT:
930            return ((char[])data)[index] & 0xffff;
931        case TIFFTag.TIFF_SSHORT:
932            return ((short[])data)[index];
933        case TIFFTag.TIFF_SLONG:
934            return ((int[])data)[index];
935        case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
936            return (int)((long[])data)[index];
937        case TIFFTag.TIFF_FLOAT:
938            return (int)((float[])data)[index];
939        case TIFFTag.TIFF_DOUBLE:
940            return (int)((double[])data)[index];
941        case TIFFTag.TIFF_SRATIONAL:
942            int[] ivalue = getAsSRational(index);
943            return (int)((double)ivalue[0]/ivalue[1]);
944        case TIFFTag.TIFF_RATIONAL:
945            long[] lvalue = getAsRational(index);
946            return (int)((double)lvalue[0]/lvalue[1]);
947        case TIFFTag.TIFF_ASCII:
948             String s = ((String[])data)[index];
949             return (int)Double.parseDouble(s);
950        default:
951            throw new ClassCastException();
952        }
953    }
954
955    /**
956     * Returns data in any format as a <code>long</code>.
957     *
958     * <p> <code>TIFFTag.TIFF_BYTE</code> and <code>TIFF_UNDEFINED</code> data
959     * are treated as unsigned; that is, no sign extension will take
960     * place and the returned value will be in the range [0, 255].
961     * <code>TIFF_SBYTE</code> data will be returned in the range
962     * [-128, 127].
963     *
964     * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by
965     * the <code>Double.parseDouble</code> method, with the result
966     * cast to <code>long</code>.
967     */
968    public long getAsLong(int index) {
969        switch (type) {
970        case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
971            return ((byte[])data)[index] & 0xff;
972        case TIFFTag.TIFF_SBYTE:
973            return ((byte[])data)[index];
974        case TIFFTag.TIFF_SHORT:
975            return ((char[])data)[index] & 0xffff;
976        case TIFFTag.TIFF_SSHORT:
977            return ((short[])data)[index];
978        case TIFFTag.TIFF_SLONG:
979            return ((int[])data)[index];
980        case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
981            return ((long[])data)[index];
982        case TIFFTag.TIFF_SRATIONAL:
983            int[] ivalue = getAsSRational(index);
984            return (long)((double)ivalue[0]/ivalue[1]);
985        case TIFFTag.TIFF_RATIONAL:
986            long[] lvalue = getAsRational(index);
987            return (long)((double)lvalue[0]/lvalue[1]);
988        case TIFFTag.TIFF_ASCII:
989             String s = ((String[])data)[index];
990             return (long)Double.parseDouble(s);
991        default:
992            throw new ClassCastException();
993        }
994    }
995    
996    /**
997     * Returns data in any format as a <code>float</code>.
998     * 
999     * <p> <code>TIFFTag.TIFF_BYTE</code> and <code>TIFF_UNDEFINED</code> data
1000     * are treated as unsigned; that is, no sign extension will take
1001     * place and the returned value will be in the range [0, 255].
1002     * <code>TIFF_SBYTE</code> data will be returned in the range
1003     * [-128, 127].
1004     *
1005     * <p> Data in <code>TIFF_SLONG</code>, <code>TIFF_LONG</code>,
1006     * <code>TIFF_DOUBLE</code>, or <code>TIFF_IFD_POINTER</code> format are
1007     * simply cast to <code>float</code> and may suffer from
1008     * truncation.
1009     *
1010     * <p> Data in <code>TIFF_SRATIONAL</code> or
1011     * <code>TIFF_RATIONAL</code> format are evaluated by dividing the
1012     * numerator into the denominator using double-precision
1013     * arithmetic and then casting to <code>float</code>.
1014     *
1015     * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by
1016     * the <code>Double.parseDouble</code> method, with the result
1017     * cast to <code>float</code>.
1018     */
1019    public float getAsFloat(int index) {
1020        switch (type) {
1021        case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
1022            return ((byte[])data)[index] & 0xff;
1023        case TIFFTag.TIFF_SBYTE:
1024            return ((byte[])data)[index];
1025        case TIFFTag.TIFF_SHORT:
1026            return ((char[])data)[index] & 0xffff;
1027        case TIFFTag.TIFF_SSHORT:
1028            return ((short[])data)[index];
1029        case TIFFTag.TIFF_SLONG:
1030            return ((int[])data)[index];
1031        case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
1032            return ((long[])data)[index];
1033        case TIFFTag.TIFF_FLOAT:
1034            return ((float[])data)[index];
1035        case TIFFTag.TIFF_DOUBLE:
1036            return (float)((double[])data)[index];
1037        case TIFFTag.TIFF_SRATIONAL:
1038            int[] ivalue = getAsSRational(index);
1039            return (float)((double)ivalue[0]/ivalue[1]);
1040        case TIFFTag.TIFF_RATIONAL:
1041            long[] lvalue = getAsRational(index);
1042            return (float)((double)lvalue[0]/lvalue[1]);
1043        case TIFFTag.TIFF_ASCII:
1044             String s = ((String[])data)[index];
1045             return (float)Double.parseDouble(s);
1046        default:
1047            throw new ClassCastException();
1048        }
1049    }
1050
1051    /**
1052     * Returns data in any format as a <code>double</code>.
1053     *
1054     * <p> <code>TIFFTag.TIFF_BYTE</code> and <code>TIFF_UNDEFINED</code> data
1055     * are treated as unsigned; that is, no sign extension will take
1056     * place and the returned value will be in the range [0, 255].
1057     * <code>TIFF_SBYTE</code> data will be returned in the range
1058     * [-128, 127].
1059     *
1060     * <p> Data in <code>TIFF_SRATIONAL</code> or
1061     * <code>TIFF_RATIONAL</code> format are evaluated by dividing the
1062     * numerator into the denominator using double-precision
1063     * arithmetic.
1064     *
1065     * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by
1066     * the <code>Double.parseDouble</code> method.
1067     */
1068    public double getAsDouble(int index) {
1069        switch (type) {
1070        case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
1071            return ((byte[])data)[index] & 0xff;
1072        case TIFFTag.TIFF_SBYTE:
1073            return ((byte[])data)[index];
1074        case TIFFTag.TIFF_SHORT:
1075            return ((char[])data)[index] & 0xffff;
1076        case TIFFTag.TIFF_SSHORT:
1077            return ((short[])data)[index];
1078        case TIFFTag.TIFF_SLONG:
1079            return ((int[])data)[index];
1080        case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
1081            return ((long[])data)[index];
1082        case TIFFTag.TIFF_FLOAT:
1083            return ((float[])data)[index];
1084        case TIFFTag.TIFF_DOUBLE:
1085            return ((double[])data)[index];
1086        case TIFFTag.TIFF_SRATIONAL:
1087            int[] ivalue = getAsSRational(index);
1088            return (double)ivalue[0]/ivalue[1];
1089        case TIFFTag.TIFF_RATIONAL:
1090            long[] lvalue = getAsRational(index);
1091            return (double)lvalue[0]/lvalue[1];
1092        case TIFFTag.TIFF_ASCII:
1093             String s = ((String[])data)[index];
1094             return Double.parseDouble(s);
1095        default:
1096            throw new ClassCastException();
1097        }
1098    }
1099
1100    /**
1101     * Returns a <code>TIFFTag.TIFF_ASCII</code> value as a
1102     * <code>String</code>.
1103     *
1104     * @throws ClassCastException if the field is not of type
1105     * <code>TIFF_ASCII</code>.
1106     */
1107    public String getAsString(int index) {
1108        return ((String[])data)[index];
1109    }
1110
1111    /**
1112     * Returns a <code>TIFFTag.TIFF_SRATIONAL</code> data item as a
1113     * two-element array of <code>int</code>s.
1114     *
1115     * @throws ClassCastException if the field is not of type
1116     * <code>TIFF_SRATIONAL</code>.
1117     */
1118    public int[] getAsSRational(int index) {
1119        return ((int[][])data)[index];
1120    }
1121
1122    /**
1123     * Returns a TIFFTag.TIFF_RATIONAL data item as a two-element array
1124     * of ints.
1125     *
1126     * @throws ClassCastException if the field is not of type
1127     * <code>TIFF_RATIONAL</code>.
1128     */
1129    public long[] getAsRational(int index) {
1130        return ((long[][])data)[index];
1131    }
1132
1133
1134    /**
1135     * Returns a <code>String</code> containing a human-readable
1136     * version of the data item.  Data of type
1137     * <code>TIFFTag.TIFF_RATIONAL</code> or <code>TIFF_SRATIONAL</code> are
1138     * represented as a pair of integers separated by a
1139     * <code>'/'</code> character.
1140     *
1141     * @throws ClassCastException if the field is not of one of the
1142     * legal field types.
1143     */
1144    public String getValueAsString(int index) {
1145        switch (type) {
1146        case TIFFTag.TIFF_ASCII:
1147            return ((String[])data)[index];
1148        case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED:
1149            return Integer.toString(((byte[])data)[index] & 0xff);
1150        case TIFFTag.TIFF_SBYTE:
1151            return Integer.toString(((byte[])data)[index]);
1152        case TIFFTag.TIFF_SHORT:
1153            return Integer.toString(((char[])data)[index] & 0xffff);
1154        case TIFFTag.TIFF_SSHORT:
1155            return Integer.toString(((short[])data)[index]);
1156        case TIFFTag.TIFF_SLONG:
1157            return Integer.toString(((int[])data)[index]);
1158        case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER:
1159            return Long.toString(((long[])data)[index]);
1160        case TIFFTag.TIFF_FLOAT:
1161            return Float.toString(((float[])data)[index]);
1162        case TIFFTag.TIFF_DOUBLE:
1163            return Double.toString(((double[])data)[index]);
1164        case TIFFTag.TIFF_SRATIONAL:
1165            int[] ivalue = getAsSRational(index);
1166            String srationalString;
1167            if(ivalue[1] != 0 && ivalue[0] % ivalue[1] == 0) {
1168                // If the denominator is a non-zero integral divisor
1169                // of the numerator then convert the fraction to be
1170                // with respect to a unity denominator.
1171                srationalString =
1172                    Integer.toString(ivalue[0] / ivalue[1]) + "/1";
1173            } else {
1174                // Use the values directly.
1175                srationalString =
1176                    Integer.toString(ivalue[0]) +
1177                    "/" +
1178                    Integer.toString(ivalue[1]);
1179            }
1180            return srationalString;
1181        case TIFFTag.TIFF_RATIONAL:
1182            long[] lvalue = getAsRational(index);
1183            String rationalString;
1184            if(lvalue[1] != 0L && lvalue[0] % lvalue[1] == 0) {
1185                // If the denominator is a non-zero integral divisor
1186                // of the numerator then convert the fraction to be
1187                // with respect to a unity denominator.
1188                rationalString =
1189                    Long.toString(lvalue[0] / lvalue[1]) + "/1";
1190            } else {
1191                // Use the values directly.
1192                rationalString =
1193                    Long.toString(lvalue[0]) +
1194                    "/" +
1195                    Long.toString(lvalue[1]);
1196            }
1197            return rationalString;
1198        default:
1199            throw new ClassCastException();
1200        }
1201    }
1202
1203    /**
1204     * Compares this <code>TIFFField</code> with another
1205     * <code>TIFFField</code> by comparing the tags.
1206     *
1207     * <p><b>Note: this class has a natural ordering that is inconsistent
1208     * with <code>equals()</code>.</b>
1209     *
1210     * @throws IllegalArgumentException if the parameter is <code>null</code>.
1211     * @throws ClassCastException if the parameter is not a
1212     *         <code>TIFFField</code>.
1213     */
1214    public int compareTo(Object o) {
1215        if (o == null) {
1216            throw new IllegalArgumentException();
1217        }
1218
1219        int oTagNumber = ((TIFFField)o).getTagNumber();
1220        if (tagNumber < oTagNumber) {
1221            return -1;
1222        } else if (tagNumber > oTagNumber) {
1223            return 1;
1224        } else {
1225            return 0;
1226        }
1227    }
1228}