1 /* 2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.imageio.plugins.tiff; 26 27 import java.util.Iterator; 28 import java.util.Set; 29 import java.util.SortedMap; 30 import 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 1.9 44 * @see BaselineTIFFTagSet 45 * @see TIFFField 46 * @see TIFFTagSet 47 */ 48 public 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</code>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</code> 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</code>. 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</code> with a given name, tag number and 187 * <code>TIFFTagSet</code> 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</code> will 190 * represent the set of <code>TIFFTag</code>s which appear in the IFD 191 * pointed to. A <code>TIFFTag</code> represents an IFD pointer if and 192 * only if <code>tagSet</code> is non-<code>null</code> or the data 193 * type <code>TIFF_IFD_POINTER</code> 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</code> 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</code> 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</code>. 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</code> is 240 * less than <code>MIN_DATATYPE</code> or greater than 241 * <code>MAX_DATATYPE</code>. 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</code>. 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</code>. 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 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG) 277 * </pre> 278 * 279 * @return an <code>int</code> 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</code> 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</code> field is <code>SamplesPerPixel</code>, 292 * or it may be variable as in the case of most <code>US-ASCII</code> 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</code> 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>, <code>TIFF_SHORT</code>, etc. 307 * 308 * @return a <code>boolean</code> indicating whether the given 309 * data type may be used with this tag. 310 * 311 * @throws IllegalArgumentException if <code>datatype</code> is 312 * less than <code>MIN_DATATYPE</code> or greater than 313 * <code>MAX_DATATYPE</code>. 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</code> of which this tag is a part. 324 * 325 * @return the containing <code>TIFFTagSet</code>. 326 */ 327 public TIFFTagSet getTagSet() { 328 return tagSet; 329 } 330 331 /** 332 * Returns <code>true</code> if this tag is used to point to an IFD 333 * structure containing additional tags. A <code>TIFFTag</code> represents 334 * an IFD pointer if and only if its <code>TIFFTagSet</code> is 335 * non-<code>null</code> or the data type <code>TIFF_IFD_POINTER</code> is 336 * legal. This condition will be satisfied if and only if either 337 * <code>getTagSet() != null</code> or 338 * <code>isDataTypeOK(TIFF_IFD_POINTER) == true</code>. 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</code> 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</code> 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</code> 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</code> 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</code>. 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 }