blob: 33f88f9e34cf4e83dd96c5e908ac01578bebbcbd [file] [log] [blame]
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.imageio.plugins.tiff;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* A class defining the notion of a TIFF tag. A TIFF tag is a key
* that may appear in an Image File Directory (IFD). In the IFD
* each tag has some data associated with it, which may consist of zero
* or more values of a given data type. The combination of a tag and a
* value is known as an IFD Entry or TIFF Field.
*
* <p> The actual tag values used in the root IFD of a standard ("baseline")
* tiff stream are defined in the {@link BaselineTIFFTagSet
* BaselineTIFFTagSet} class.
*
* @since 9
* @see BaselineTIFFTagSet
* @see TIFFField
* @see TIFFTagSet
*/
public class TIFFTag {
// TIFF 6.0 + Adobe PageMaker(R) 6.0 TIFF Technical Notes 1 IFD data type
/** Flag for 8 bit unsigned integers. */
public static final int TIFF_BYTE = 1;
/** Flag for null-terminated ASCII strings. */
public static final int TIFF_ASCII = 2;
/** Flag for 16 bit unsigned integers. */
public static final int TIFF_SHORT = 3;
/** Flag for 32 bit unsigned integers. */
public static final int TIFF_LONG = 4;
/** Flag for pairs of 32 bit unsigned integers. */
public static final int TIFF_RATIONAL = 5;
/** Flag for 8 bit signed integers. */
public static final int TIFF_SBYTE = 6;
/** Flag for 8 bit uninterpreted bytes. */
public static final int TIFF_UNDEFINED = 7;
/** Flag for 16 bit signed integers. */
public static final int TIFF_SSHORT = 8;
/** Flag for 32 bit signed integers. */
public static final int TIFF_SLONG = 9;
/** Flag for pairs of 32 bit signed integers. */
public static final int TIFF_SRATIONAL = 10;
/** Flag for 32 bit IEEE floats. */
public static final int TIFF_FLOAT = 11;
/** Flag for 64 bit IEEE doubles. */
public static final int TIFF_DOUBLE = 12;
/**
* Flag for IFD pointer defined in TIFF Tech Note 1 in
* TIFF Specification Supplement 1.
*/
public static final int TIFF_IFD_POINTER = 13;
/**
* The numerically smallest constant representing a TIFF data type.
*/
public static final int MIN_DATATYPE = TIFF_BYTE;
/**
* The numerically largest constant representing a TIFF data type.
*/
public static final int MAX_DATATYPE = TIFF_IFD_POINTER;
/**
* The name assigned to a tag with an unknown tag number. Such
* a tag may be created for example when reading an IFD and a
* tag number is encountered which is not in any of the
* {@code TIFFTagSet}s known to the reader.
*/
public static final String UNKNOWN_TAG_NAME = "UnknownTag";
/**
* Disallowed data type mask.
*/
private static final int DISALLOWED_DATATYPES_MASK = ~0x3fff;
private static final int[] SIZE_OF_TYPE = {
0, // 0 = n/a
1, // 1 = byte
1, // 2 = ascii
2, // 3 = short
4, // 4 = long
8, // 5 = rational
1, // 6 = sbyte
1, // 7 = undefined
2, // 8 = sshort
4, // 9 = slong
8, // 10 = srational
4, // 11 = float
8, // 12 = double
4, // 13 = IFD_POINTER
};
private int number;
private String name;
private int dataTypes;
private int count;
private TIFFTagSet tagSet = null;
// Mnemonic names for integral enumerated constants
private SortedMap<Integer,String> valueNames = null;
/**
* Constructs a {@code TIFFTag} with a given name, tag number, set
* of legal data types, and value count. A negative value count signifies
* that either an arbitrary number of values is legal or the required count
* is determined by the values of other fields in the IFD. A non-negative
* count specifies the number of values which an associated field must
* contain. The tag will have no associated {@code TIFFTagSet}.
*
* <p> If there are mnemonic names to be associated with the legal
* data values for the tag, {@link #addValueName(int, String)
* addValueName()} should be called on the new instance for each name.
* Mnemonic names apply only to tags which have integral data type.</p>
*
* <p> See the documentation for {@link #getDataTypes()
* getDataTypes()} for an explanation of how the set
* of data types is to be converted into a bit mask.</p>
*
* @param name the name of the tag.
* @param number the number used to represent the tag.
* @param dataTypes a bit mask indicating the set of legal data
* types for this tag.
* @param count the value count for this tag.
* @throws NullPointerException if name is null.
* @throws IllegalArgumentException if number is negative or dataTypes
* is negative or specifies an out of range type.
*/
public TIFFTag(String name, int number, int dataTypes, int count) {
if (name == null) {
throw new NullPointerException("name == null");
} else if (number < 0) {
throw new IllegalArgumentException("number (" + number + ") < 0");
} else if (dataTypes < 0
|| (dataTypes & DISALLOWED_DATATYPES_MASK) != 0) {
throw new IllegalArgumentException("dataTypes out of range");
}
this.name = name;
this.number = number;
this.dataTypes = dataTypes;
this.count = count;
}
/**
* Constructs a {@code TIFFTag} with a given name, tag number and
* {@code TIFFTagSet} to which it refers. The legal data types are
* set to include {@link #TIFF_LONG} and {@link #TIFF_IFD_POINTER} and the
* value count is unity. The {@code TIFFTagSet} will
* represent the set of {@code TIFFTag}s which appear in the IFD
* pointed to. A {@code TIFFTag} represents an IFD pointer if and
* only if {@code tagSet} is non-{@code null} or the data
* type {@code TIFF_IFD_POINTER} is legal.
*
* @param name the name of the tag.
* @param number the number used to represent the tag.
* @param tagSet the {@code TIFFTagSet} to which this tag belongs.
* @throws NullPointerException if name or tagSet is null.
* @throws IllegalArgumentException if number is negative.
*
* @see #TIFFTag(String, int, int, int)
*/
public TIFFTag(String name, int number, TIFFTagSet tagSet) {
this(name, number,
1 << TIFFTag.TIFF_LONG | 1 << TIFFTag.TIFF_IFD_POINTER, 1);
if (tagSet == null) {
throw new NullPointerException("tagSet == null");
}
this.tagSet = tagSet;
}
/**
* Constructs a {@code TIFFTag} with a given name, tag number,
* and set of legal data types. The value count of the tag will be
* undefined and it will have no associated {@code TIFFTagSet}.
*
* @param name the name of the tag.
* @param number the number used to represent the tag.
* @param dataTypes a bit mask indicating the set of legal data
* types for this tag.
* @throws NullPointerException if name is null.
* @throws IllegalArgumentException if number is negative or dataTypes
* is negative or specifies an out of range type.
*
* @see #TIFFTag(String, int, int, int)
*/
public TIFFTag(String name, int number, int dataTypes) {
this(name, number, dataTypes, -1);
}
/**
* Returns the number of bytes used to store a value of the given
* data type.
*
* @param dataType the data type to be queried.
*
* @return the number of bytes used to store the given data type.
*
* @throws IllegalArgumentException if {@code datatype} is
* less than {@code MIN_DATATYPE} or greater than
* {@code MAX_DATATYPE}.
*/
public static int getSizeOfType(int dataType) {
if (dataType < MIN_DATATYPE ||dataType > MAX_DATATYPE) {
throw new IllegalArgumentException("dataType out of range!");
}
return SIZE_OF_TYPE[dataType];
}
/**
* Returns the name of the tag, as it will appear in image metadata.
*
* @return the tag name, as a {@code String}.
*/
public String getName() {
return name;
}
/**
* Returns the integer used to represent the tag.
*
* @return the tag number, as an {@code int}.
*/
public int getNumber() {
return number;
}
/**
* Returns a bit mask indicating the set of data types that may
* be used to store the data associated with the tag.
* For example, a tag that can store both SHORT and LONG values
* would return a value of:
*
* <pre>
* (1 &lt;&lt; TIFFTag.TIFF_SHORT) | (1 &lt;&lt; TIFFTag.TIFF_LONG)
* </pre>
*
* @return an {@code int} containing a bitmask encoding the
* set of valid data types.
*/
public int getDataTypes() {
return dataTypes;
}
/**
* Returns the value count of this tag. If this value is positive, it
* represents the required number of values for a {@code TIFFField}
* which has this tag. If the value is negative, the count is undefined.
* In the latter case the count may be derived, e.g., the number of values
* of the {@code BitsPerSample} field is {@code SamplesPerPixel},
* or it may be variable as in the case of most {@code US-ASCII}
* fields.
*
* @return the value count of this tag.
*/
public int getCount() {
return count;
}
/**
* Returns {@code true} if the given data type
* may be used for the data associated with this tag.
*
* @param dataType the data type to be queried, one of
* {@code TIFF_BYTE}, {@code TIFF_SHORT}, etc.
*
* @return a {@code boolean} indicating whether the given
* data type may be used with this tag.
*
* @throws IllegalArgumentException if {@code datatype} is
* less than {@code MIN_DATATYPE} or greater than
* {@code MAX_DATATYPE}.
*/
public boolean isDataTypeOK(int dataType) {
if (dataType < MIN_DATATYPE || dataType > MAX_DATATYPE) {
throw new IllegalArgumentException("datatype not in range!");
}
return (dataTypes & (1 << dataType)) != 0;
}
/**
* Returns the {@code TIFFTagSet} of which this tag is a part.
*
* @return the containing {@code TIFFTagSet}.
*/
public TIFFTagSet getTagSet() {
return tagSet;
}
/**
* Returns {@code true} if this tag is used to point to an IFD
* structure containing additional tags. A {@code TIFFTag} represents
* an IFD pointer if and only if its {@code TIFFTagSet} is
* non-{@code null} or the data type {@code TIFF_IFD_POINTER} is
* legal. This condition will be satisfied if and only if either
* {@code getTagSet() != null} or
* {@code isDataTypeOK(TIFF_IFD_POINTER) == true}.
*
* <p>Many TIFF extensions use the IFD mechanism in order to limit the
* number of new tags that may appear in the root IFD.</p>
*
* @return {@code true} if this tag points to an IFD.
*/
public boolean isIFDPointer() {
return tagSet != null || isDataTypeOK(TIFF_IFD_POINTER);
}
/**
* Returns {@code true} if there are mnemonic names associated with
* the set of legal values for the data associated with this tag. Mnemonic
* names apply only to tags which have integral data type.
*
* @return {@code true} if mnemonic value names are available.
*/
public boolean hasValueNames() {
return valueNames != null;
}
/**
* Adds a mnemonic name for a particular value that this tag's data may take
* on. Mnemonic names apply only to tags which have integral data type.
*
* @param value the data value.
* @param name the name to associate with the value.
*/
protected void addValueName(int value, String name) {
if (valueNames == null) {
valueNames = new TreeMap<Integer,String>();
}
valueNames.put(Integer.valueOf(value), name);
}
/**
* Returns the mnemonic name associated with a particular value
* that this tag's data may take on, or {@code null} if
* no name is present. Mnemonic names apply only to tags which have
* integral data type.
*
* @param value the data value.
*
* @return the mnemonic name associated with the value, as a
* {@code String}.
*/
public String getValueName(int value) {
if (valueNames == null) {
return null;
}
return valueNames.get(Integer.valueOf(value));
}
/**
* Returns an array of values for which mnemonic names are defined. The
* method {@link #getValueName(int) getValueName()} will return
* non-{@code null} only for values contained in the returned array.
* Mnemonic names apply only to tags which have integral data type.
*
* @return the values for which there is a mnemonic name.
*/
public int[] getNamedValues() {
int[] intValues = null;
if (valueNames != null) {
Set<Integer> values = valueNames.keySet();
Iterator<Integer> iter = values.iterator();
intValues = new int[values.size()];
int i = 0;
while (iter.hasNext()) {
intValues[i++] = iter.next();
}
}
return intValues;
}
}