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