1/*
2 * Copyright (c) 2005, 2016, 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 */
25package javax.imageio.plugins.tiff;
26
27import java.util.Iterator;
28import java.util.Set;
29import java.util.SortedMap;
30import java.util.TreeMap;
31
32/**
33 * A class defining the notion of a TIFF tag.  A TIFF tag is a key
34 * that may appear in an Image File Directory (IFD).  In the IFD
35 * each tag has some data associated with it, which may consist of zero
36 * or more values of a given data type. The combination of a tag and a
37 * value is known as an IFD Entry or TIFF Field.
38 *
39 * <p> The actual tag values used in the root IFD of a standard ("baseline")
40 * tiff stream are defined in the {@link BaselineTIFFTagSet
41 * BaselineTIFFTagSet} class.
42 *
43 * @since 9
44 * @see   BaselineTIFFTagSet
45 * @see   TIFFField
46 * @see   TIFFTagSet
47 */
48public class TIFFTag {
49
50    // TIFF 6.0 + Adobe PageMaker(R) 6.0 TIFF Technical Notes 1 IFD data type
51
52    /** Flag for 8 bit unsigned integers. */
53    public static final int TIFF_BYTE        =  1;
54
55    /** Flag for null-terminated ASCII strings. */
56    public static final int TIFF_ASCII       =  2;
57
58    /** Flag for 16 bit unsigned integers. */
59    public static final int TIFF_SHORT       =  3;
60
61    /** Flag for 32 bit unsigned integers. */
62    public static final int TIFF_LONG        =  4;
63
64    /** Flag for pairs of 32 bit unsigned integers. */
65    public static final int TIFF_RATIONAL    =  5;
66
67    /** Flag for 8 bit signed integers. */
68    public static final int TIFF_SBYTE       =  6;
69
70    /** Flag for 8 bit uninterpreted bytes. */
71    public static final int TIFF_UNDEFINED   =  7;
72
73    /** Flag for 16 bit signed integers. */
74    public static final int TIFF_SSHORT      =  8;
75
76    /** Flag for 32 bit signed integers. */
77    public static final int TIFF_SLONG       =  9;
78
79    /** Flag for pairs of 32 bit signed integers. */
80    public static final int TIFF_SRATIONAL   = 10;
81
82    /** Flag for 32 bit IEEE floats. */
83    public static final int TIFF_FLOAT       = 11;
84
85    /** Flag for 64 bit IEEE doubles. */
86    public static final int TIFF_DOUBLE      = 12;
87
88    /**
89     * Flag for IFD pointer defined in TIFF Tech Note 1 in
90     * TIFF Specification Supplement 1.
91     */
92    public static final int TIFF_IFD_POINTER = 13;
93
94    /**
95     * The numerically smallest constant representing a TIFF data type.
96     */
97    public static final int MIN_DATATYPE = TIFF_BYTE;
98
99    /**
100     * The numerically largest constant representing a TIFF data type.
101     */
102    public static final int MAX_DATATYPE = TIFF_IFD_POINTER;
103
104    /**
105     * The name assigned to a tag with an unknown tag number. Such
106     * a tag may be created for example when reading an IFD and a
107     * tag number is encountered which is not in any of the
108     * {@code TIFFTagSet}s known to the reader.
109     */
110    public static final String UNKNOWN_TAG_NAME = "UnknownTag";
111
112    /**
113     * Disallowed data type mask.
114     */
115    private static final int DISALLOWED_DATATYPES_MASK = ~0x3fff;
116
117    private static final int[] SIZE_OF_TYPE = {
118        0, //  0 = n/a
119        1, //  1 = byte
120        1, //  2 = ascii
121        2, //  3 = short
122        4, //  4 = long
123        8, //  5 = rational
124        1, //  6 = sbyte
125        1, //  7 = undefined
126        2, //  8 = sshort
127        4, //  9 = slong
128        8, // 10 = srational
129        4, // 11 = float
130        8, // 12 = double
131        4, // 13 = IFD_POINTER
132    };
133
134    private int number;
135    private String name;
136    private int dataTypes;
137    private int count;
138    private TIFFTagSet tagSet = null;
139
140    // Mnemonic names for integral enumerated constants
141    private SortedMap<Integer,String> valueNames = null;
142
143    /**
144     * Constructs a {@code TIFFTag} with a given name, tag number, set
145     * of legal data types, and value count. A negative value count signifies
146     * that either an arbitrary number of values is legal or the required count
147     * is determined by the values of other fields in the IFD. A non-negative
148     * count specifies the number of values which an associated field must
149     * contain. The tag will have no associated {@code TIFFTagSet}.
150     *
151     * <p> If there are mnemonic names to be associated with the legal
152     * data values for the tag, {@link #addValueName(int, String)
153     * addValueName()} should be called on the new instance for each name.
154     * Mnemonic names apply only to tags which have integral data type.</p>
155     *
156     * <p> See the documentation for {@link #getDataTypes()
157     * getDataTypes()} for an explanation of how the set
158     * of data types is to be converted into a bit mask.</p>
159     *
160     * @param name the name of the tag.
161     * @param number the number used to represent the tag.
162     * @param dataTypes a bit mask indicating the set of legal data
163     * types for this tag.
164     * @param count the value count for this tag.
165     * @throws NullPointerException if name is null.
166     * @throws IllegalArgumentException if number is negative or dataTypes
167     * is negative or specifies an out of range type.
168     */
169    public TIFFTag(String name, int number, int dataTypes, int count) {
170        if (name == null) {
171            throw new NullPointerException("name == null");
172        } else if (number < 0) {
173            throw new IllegalArgumentException("number (" + number + ") < 0");
174        } else if (dataTypes < 0
175            || (dataTypes & DISALLOWED_DATATYPES_MASK) != 0) {
176            throw new IllegalArgumentException("dataTypes out of range");
177        }
178
179        this.name = name;
180        this.number = number;
181        this.dataTypes = dataTypes;
182        this.count = count;
183    }
184
185    /**
186     * Constructs a {@code TIFFTag} with a given name, tag number and
187     * {@code TIFFTagSet} to which it refers. The legal data types are
188     * set to include {@link #TIFF_LONG} and {@link #TIFF_IFD_POINTER} and the
189     * value count is unity. The {@code TIFFTagSet} will
190     * represent the set of {@code TIFFTag}s which appear in the IFD
191     * pointed to. A {@code TIFFTag} represents an IFD pointer if and
192     * only if {@code tagSet} is non-{@code null} or the data
193     * type {@code TIFF_IFD_POINTER} is legal.
194     *
195     * @param name the name of the tag.
196     * @param number the number used to represent the tag.
197     * @param tagSet the {@code TIFFTagSet} to which this tag belongs.
198     * @throws NullPointerException if name or tagSet is null.
199     * @throws IllegalArgumentException if number is negative.
200     *
201     * @see #TIFFTag(String, int, int, int)
202     */
203    public TIFFTag(String name, int number, TIFFTagSet tagSet) {
204        this(name, number,
205            1 << TIFFTag.TIFF_LONG | 1 << TIFFTag.TIFF_IFD_POINTER, 1);
206        if (tagSet == null) {
207            throw new NullPointerException("tagSet == null");
208        }
209        this.tagSet = tagSet;
210    }
211
212    /**
213     * Constructs  a  {@code TIFFTag}  with  a  given  name,  tag number,
214     * and set  of  legal  data  types.  The value count of the tag will be
215     * undefined and it will  have  no associated {@code TIFFTagSet}.
216     *
217     * @param name the name of the tag.
218     * @param number the number used to represent the tag.
219     * @param dataTypes a bit mask indicating the set of legal data
220     * types for this tag.
221     * @throws NullPointerException if name is null.
222     * @throws IllegalArgumentException if number is negative or dataTypes
223     * is negative or specifies an out of range type.
224     *
225     * @see #TIFFTag(String, int, int, int)
226     */
227    public TIFFTag(String name, int number, int dataTypes) {
228        this(name, number, dataTypes, -1);
229    }
230
231    /**
232     * Returns the number of bytes used to store a value of the given
233     * data type.
234     *
235     * @param dataType the data type to be queried.
236     *
237     * @return the number of bytes used to store the given data type.
238     *
239     * @throws IllegalArgumentException if {@code datatype} is
240     * less than {@code MIN_DATATYPE} or greater than
241     * {@code MAX_DATATYPE}.
242     */
243    public static int getSizeOfType(int dataType) {
244        if (dataType < MIN_DATATYPE ||dataType > MAX_DATATYPE) {
245            throw new IllegalArgumentException("dataType out of range!");
246        }
247
248        return SIZE_OF_TYPE[dataType];
249    }
250
251    /**
252     * Returns the name of the tag, as it will appear in image metadata.
253     *
254     * @return the tag name, as a {@code String}.
255     */
256    public String getName() {
257        return name;
258    }
259
260    /**
261     * Returns the integer used to represent the tag.
262     *
263     * @return the tag number, as an {@code int}.
264     */
265    public int getNumber() {
266        return number;
267    }
268
269    /**
270     * Returns a bit mask indicating the set of data types that may
271     * be used to store the data associated with the tag.
272     * For example, a tag that can store both SHORT and LONG values
273     * would return a value of:
274     *
275     * <pre>
276     * (1 &lt;&lt; TIFFTag.TIFF_SHORT) | (1 &lt;&lt; TIFFTag.TIFF_LONG)
277     * </pre>
278     *
279     * @return an {@code int} containing a bitmask encoding the
280     * set of valid data types.
281     */
282    public int getDataTypes() {
283        return dataTypes;
284    }
285
286    /**
287     * Returns the value count of this tag. If this value is positive, it
288     * represents the required number of values for a {@code TIFFField}
289     * which has this tag. If the value is negative, the count is undefined.
290     * In the latter case the count may be derived, e.g., the number of values
291     * of the {@code BitsPerSample} field is {@code SamplesPerPixel},
292     * or it may be variable as in the case of most {@code US-ASCII}
293     * fields.
294     *
295     * @return the value count of this tag.
296     */
297    public int getCount() {
298        return count;
299    }
300
301    /**
302     * Returns {@code true} if the given data type
303     * may be used for the data associated with this tag.
304     *
305     * @param dataType the data type to be queried, one of
306     * {@code TIFF_BYTE}, {@code TIFF_SHORT}, etc.
307     *
308     * @return a {@code boolean} indicating whether the given
309     * data type may be used with this tag.
310     *
311     * @throws IllegalArgumentException if {@code datatype} is
312     * less than {@code MIN_DATATYPE} or greater than
313     * {@code MAX_DATATYPE}.
314     */
315    public boolean isDataTypeOK(int dataType) {
316        if (dataType < MIN_DATATYPE || dataType > MAX_DATATYPE) {
317            throw new IllegalArgumentException("datatype not in range!");
318        }
319        return (dataTypes & (1 << dataType)) != 0;
320    }
321
322    /**
323     * Returns the {@code TIFFTagSet} of which this tag is a part.
324     *
325     * @return the containing {@code TIFFTagSet}.
326     */
327    public TIFFTagSet getTagSet() {
328        return tagSet;
329    }
330
331    /**
332     * Returns {@code true} if this tag is used to point to an IFD
333     * structure containing additional tags. A {@code TIFFTag} represents
334     * an IFD pointer if and only if its {@code TIFFTagSet} is
335     * non-{@code null} or the data type {@code TIFF_IFD_POINTER} is
336     * legal. This condition will be satisfied if and only if either
337     * {@code getTagSet() != null} or
338     * {@code isDataTypeOK(TIFF_IFD_POINTER) == true}.
339     *
340     * <p>Many TIFF extensions use the IFD mechanism in order to limit the
341     * number of new tags that may appear in the root IFD.</p>
342     *
343     * @return {@code true} if this tag points to an IFD.
344     */
345    public boolean isIFDPointer() {
346        return tagSet != null || isDataTypeOK(TIFF_IFD_POINTER);
347    }
348
349    /**
350     * Returns {@code true} if there are mnemonic names associated with
351     * the set of legal values for the data associated with this tag.  Mnemonic
352     * names apply only to tags which have integral data type.
353     *
354     * @return {@code true} if mnemonic value names are available.
355     */
356    public boolean hasValueNames() {
357        return valueNames != null;
358    }
359
360    /**
361     * Adds a mnemonic name for a particular value that this tag's data may take
362     * on.  Mnemonic names apply only to tags which have integral data type.
363     *
364     * @param value the data value.
365     * @param name the name to associate with the value.
366     */
367    protected void addValueName(int value, String name) {
368        if (valueNames == null) {
369            valueNames = new TreeMap<Integer,String>();
370        }
371        valueNames.put(Integer.valueOf(value), name);
372    }
373
374    /**
375     * Returns the mnemonic name associated with a particular value
376     * that this tag's data may take on, or {@code null} if
377     * no name is present.  Mnemonic names apply only to tags which have
378     * integral data type.
379     *
380     * @param value the data value.
381     *
382     * @return the mnemonic name associated with the value, as a
383     * {@code String}.
384     */
385    public String getValueName(int value) {
386        if (valueNames == null) {
387            return null;
388        }
389        return valueNames.get(Integer.valueOf(value));
390    }
391
392    /**
393     * Returns an array of values for which mnemonic names are defined.  The
394     * method {@link #getValueName(int) getValueName()} will return
395     * non-{@code null} only for values contained in the returned array.
396     * Mnemonic names apply only to tags which have integral data type.
397     *
398     * @return the values for which there is a mnemonic name.
399     */
400    public int[] getNamedValues() {
401        int[] intValues = null;
402        if (valueNames != null) {
403            Set<Integer> values = valueNames.keySet();
404            Iterator<Integer> iter = values.iterator();
405            intValues = new int[values.size()];
406            int i = 0;
407            while (iter.hasNext()) {
408                intValues[i++] = iter.next();
409            }
410        }
411        return intValues;
412    }
413}
414