1 /* 2 * Copyright (c) 2005, 2017, 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.StringTokenizer; 28 import org.w3c.dom.NamedNodeMap; 29 import org.w3c.dom.Node; 30 import com.sun.imageio.plugins.tiff.TIFFFieldNode; 31 import com.sun.imageio.plugins.tiff.TIFFIFD; 32 33 /** 34 * A class representing a field in a TIFF 6.0 Image File Directory. 35 * 36 * <p> A field in a TIFF Image File Directory (IFD) is defined as a 37 * tag number accompanied by a sequence of values of identical data type. 38 * TIFF 6.0 defines 12 data types; a 13th type {@code IFD} is 39 * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These 40 * TIFF data types are referred to by Java constants and mapped internally 41 * onto Java language data types and type names as follows: 42 * 43 * <table class="striped"> 44 * <caption>TIFF Data Type to Java Data Type Mapping</caption> 45 * <thead> 46 * <tr> 47 * <th scope="col">TIFF Data Type 48 * <th scope="col">Java Constant 49 * <th scope="col">Java Data Type 50 * <th scope="col">Java Type Name 51 * </thead> 52 * <tbody> 53 * <tr> 54 * <th scope="row">{@code BYTE} 55 * <td>{@link TIFFTag#TIFF_BYTE} 56 * <td>{@code byte} 57 * <td>{@code "Byte"} 58 * <tr> 59 * <th scope="row">{@code ASCII} 60 * <td>{@link TIFFTag#TIFF_ASCII} 61 * <td>{@code String} 62 * <td>{@code "Ascii"} 63 * <tr> 64 * <th scope="row">{@code SHORT} 65 * <td>{@link TIFFTag#TIFF_SHORT} 66 * <td>{@code char} 67 * <td>{@code "Short"} 68 * <tr> 69 * <th scope="row">{@code LONG} 70 * <td>{@link TIFFTag#TIFF_LONG} 71 * <td>{@code long} 72 * <td>{@code "Long"} 73 * <tr> 74 * <th scope="row">{@code RATIONAL} 75 * <td>{@link TIFFTag#TIFF_RATIONAL} 76 * <td>{@code long[2]} {numerator, denominator} 77 * <td>{@code "Rational"} 78 * <tr> 79 * <th scope="row">{@code SBYTE} 80 * <td>{@link TIFFTag#TIFF_SBYTE} 81 * <td>{@code byte} 82 * <td>{@code "SByte"} 83 * <tr> 84 * <th scope="row">{@code UNDEFINED} 85 * <td>{@link TIFFTag#TIFF_UNDEFINED} 86 * <td>{@code byte} 87 * <td>{@code "Undefined"} 88 * <tr> 89 * <th scope="row">{@code SSHORT} 90 * <td>{@link TIFFTag#TIFF_SSHORT} 91 * <td>{@code short} 92 * <td>{@code "SShort"} 93 * <tr> 94 * <th scope="row">{@code SLONG} 95 * <td>{@link TIFFTag#TIFF_SLONG} 96 * <td>{@code int} 97 * <td>{@code "SLong"} 98 * <tr> 99 * <th scope="row">{@code SRATIONAL} 100 * <td>{@link TIFFTag#TIFF_SRATIONAL} 101 * <td>{@code int[2]} {numerator, denominator} 102 * <td>{@code "SRational"} 103 * <tr> 104 * <th scope="row">{@code FLOAT} 105 * <td>{@link TIFFTag#TIFF_FLOAT} 106 * <td>{@code float} 107 * <td>{@code "Float"} 108 * <tr> 109 * <th scope="row">{@code DOUBLE} 110 * <td>{@link TIFFTag#TIFF_DOUBLE} 111 * <td>{@code double} 112 * <td>{@code "Double"} 113 * <tr> 114 * <th scope="row">{@code IFD} 115 * <td>{@link TIFFTag#TIFF_IFD_POINTER} 116 * <td>{@code long} 117 * <td>{@code "IFDPointer"} 118 * </tr> 119 * </tbody> 120 * </table> 121 * 122 * @since 9 123 * @see TIFFDirectory 124 * @see TIFFTag 125 */ 126 public final class TIFFField implements Cloneable { 127 128 private static final long MAX_UINT32 = 0xffffffffL; 129 130 private static final String[] TYPE_NAMES = { 131 null, 132 "Byte", "Ascii", "Short", "Long", "Rational", 133 "SByte", "Undefined", "SShort", "SLong", "SRational", 134 "Float", "Double", "IFDPointer" 135 }; 136 137 private static final boolean[] IS_INTEGRAL = { 138 false, 139 true, false, true, true, false, 140 true, true, true, true, false, 141 false, false, false 142 }; 143 144 /** The tag. */ 145 private TIFFTag tag; 146 147 /** The tag number. */ 148 private int tagNumber; 149 150 /** The tag type. */ 151 private int type; 152 153 /** The number of data items present in the field. */ 154 private int count; 155 156 /** The field data. */ 157 private Object data; 158 159 /** The IFD contents if available. This will usually be a TIFFIFD. */ 160 private TIFFDirectory dir; 161 162 /** The default constructor. */ 163 private TIFFField() {} 164 165 private static String getAttribute(Node node, String attrName) { 166 NamedNodeMap attrs = node.getAttributes(); 167 return attrs.getNamedItem(attrName).getNodeValue(); 168 } 169 170 private static void initData(Node node, 171 int[] otype, int[] ocount, Object[] odata) { 172 int type; 173 int count; 174 Object data = null; 175 176 String typeName = node.getNodeName(); 177 typeName = typeName.substring(4); 178 typeName = typeName.substring(0, typeName.length() - 1); 179 type = TIFFField.getTypeByName(typeName); 180 if (type == -1) { 181 throw new IllegalArgumentException("typeName = " + typeName); 182 } 183 184 Node child = node.getFirstChild(); 185 186 count = 0; 187 while (child != null) { 188 String childTypeName = child.getNodeName().substring(4); 189 if (!typeName.equals(childTypeName)) { 190 // warning 191 } 192 193 ++count; 194 child = child.getNextSibling(); 195 } 196 197 if (count > 0) { 198 data = createArrayForType(type, count); 199 child = node.getFirstChild(); 200 int idx = 0; 201 while (child != null) { 202 String value = getAttribute(child, "value"); 203 204 String numerator, denominator; 205 int slashPos; 206 207 switch (type) { 208 case TIFFTag.TIFF_ASCII: 209 ((String[])data)[idx] = value; 210 break; 211 case TIFFTag.TIFF_BYTE: 212 case TIFFTag.TIFF_SBYTE: 213 ((byte[])data)[idx] = 214 (byte)Integer.parseInt(value); 215 break; 216 case TIFFTag.TIFF_SHORT: 217 ((char[])data)[idx] = 218 (char)Integer.parseInt(value); 219 break; 220 case TIFFTag.TIFF_SSHORT: 221 ((short[])data)[idx] = 222 (short)Integer.parseInt(value); 223 break; 224 case TIFFTag.TIFF_SLONG: 225 ((int[])data)[idx] = 226 Integer.parseInt(value); 227 break; 228 case TIFFTag.TIFF_LONG: 229 case TIFFTag.TIFF_IFD_POINTER: 230 ((long[])data)[idx] = 231 Long.parseLong(value); 232 break; 233 case TIFFTag.TIFF_FLOAT: 234 ((float[])data)[idx] = 235 Float.parseFloat(value); 236 break; 237 case TIFFTag.TIFF_DOUBLE: 238 ((double[])data)[idx] = 239 Double.parseDouble(value); 240 break; 241 case TIFFTag.TIFF_SRATIONAL: 242 slashPos = value.indexOf("/"); 243 numerator = value.substring(0, slashPos); 244 denominator = value.substring(slashPos + 1); 245 246 ((int[][])data)[idx] = new int[2]; 247 ((int[][])data)[idx][0] = 248 Integer.parseInt(numerator); 249 ((int[][])data)[idx][1] = 250 Integer.parseInt(denominator); 251 break; 252 case TIFFTag.TIFF_RATIONAL: 253 slashPos = value.indexOf("/"); 254 numerator = value.substring(0, slashPos); 255 denominator = value.substring(slashPos + 1); 256 257 ((long[][])data)[idx] = new long[2]; 258 ((long[][])data)[idx][0] = 259 Long.parseLong(numerator); 260 ((long[][])data)[idx][1] = 261 Long.parseLong(denominator); 262 break; 263 default: 264 // error 265 } 266 267 idx++; 268 child = child.getNextSibling(); 269 } 270 } 271 272 otype[0] = type; 273 ocount[0] = count; 274 odata[0] = data; 275 } 276 277 /** 278 * Creates a {@code TIFFField} from a TIFF native image 279 * metadata node. If the value of the {@code "number"} attribute 280 * of the node is not found in {@code tagSet} then a new 281 * {@code TIFFTag} with name {@code TIFFTag.UNKNOWN_TAG_NAME} 282 * will be created and assigned to the field. 283 * 284 * @param tagSet The {@code TIFFTagSet} to which the 285 * {@code TIFFTag} of the field belongs. 286 * @param node A native TIFF image metadata {@code TIFFField} node. 287 * @throws IllegalArgumentException If the {@code Node} parameter content 288 * does not adhere to the {@code TIFFField} element structure defined by 289 * the <a href="../../metadata/doc-files/tiff_metadata.html#ImageMetadata"> 290 * TIFF native image metadata format specification</a>, or if the 291 * combination of node attributes and data is not legal per the 292 * {@link #TIFFField(TIFFTag,int,int,Object)} constructor specification. 293 * Note that a cause might be set on such an exception. 294 * @return A new {@code TIFFField}. 295 */ 296 public static TIFFField createFromMetadataNode(TIFFTagSet tagSet, 297 Node node) { 298 if (node == null) { 299 // This method is specified to throw only IllegalArgumentExceptions 300 // so we create an IAE with a NullPointerException as its cause. 301 throw new IllegalArgumentException(new NullPointerException 302 ("node == null!")); 303 } 304 String name = node.getNodeName(); 305 if (!name.equals("TIFFField")) { 306 throw new IllegalArgumentException("!name.equals(\"TIFFField\")"); 307 } 308 309 int tagNumber = Integer.parseInt(getAttribute(node, "number")); 310 TIFFTag tag = null; 311 if (tagSet != null) { 312 tag = tagSet.getTag(tagNumber); 313 } 314 315 int type = TIFFTag.TIFF_UNDEFINED; 316 int count = 0; 317 Object data = null; 318 319 Node child = node.getFirstChild(); 320 if (child != null) { 321 String typeName = child.getNodeName(); 322 if (typeName.equals("TIFFUndefined")) { 323 String values = getAttribute(child, "value"); 324 StringTokenizer st = new StringTokenizer(values, ","); 325 count = st.countTokens(); 326 327 byte[] bdata = new byte[count]; 328 for (int i = 0; i < count; i++) { 329 bdata[i] = (byte)Integer.parseInt(st.nextToken()); 330 } 331 332 type = TIFFTag.TIFF_UNDEFINED; 333 data = bdata; 334 } else { 335 int[] otype = new int[1]; 336 int[] ocount = new int[1]; 337 Object[] odata = new Object[1]; 338 339 initData(node.getFirstChild(), otype, ocount, odata); 340 type = otype[0]; 341 count = ocount[0]; 342 data = odata[0]; 343 } 344 } else if (tag != null) { 345 int t = TIFFTag.MAX_DATATYPE; 346 while(t >= TIFFTag.MIN_DATATYPE && !tag.isDataTypeOK(t)) { 347 t--; 348 } 349 type = t; 350 } 351 352 if (tag == null) { 353 tag = new TIFFTag(TIFFTag.UNKNOWN_TAG_NAME, tagNumber, 1 << type); 354 } 355 356 TIFFField field; 357 try { 358 field = new TIFFField(tag, type, count, data); 359 } catch (NullPointerException npe) { 360 // This method is specified to throw only IllegalArgumentExceptions 361 // so we catch the NullPointerException and set it as the cause of 362 // the IAE which is thrown. 363 throw new IllegalArgumentException(npe); 364 } 365 366 return field; 367 } 368 369 /** 370 * Constructs a {@code TIFFField} with arbitrary data. The 371 * {@code type} parameter must be a value for which 372 * {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()} 373 * returns {@code true}. The {@code data} parameter must 374 * be an array of a Java type appropriate for the type of the TIFF 375 * field. 376 * 377 * <p>Note that the value (data) of the {@code TIFFField} 378 * will always be the actual field value regardless of the number of 379 * bytes required for that value. This is the case despite the fact 380 * that the TIFF <i>IFD Entry</i> corresponding to the field may 381 * actually contain the offset to the value of the field rather than 382 * the value itself (the latter occurring if and only if the 383 * value fits into 4 bytes). In other words, the value of the 384 * field will already have been read from the TIFF stream. (An exception 385 * to this case may occur when the field represents the contents of a 386 * non-baseline IFD. In that case the data will be a {@code long[]} 387 * containing the offset to the IFD and the {@code TIFFDirectory} 388 * returned by {@link #getDirectory()} will be its contents.) 389 * 390 * @param tag The tag to associated with this field. 391 * @param type One of the {@code TIFFTag.TIFF_*} constants 392 * indicating the data type of the field as written to the TIFF stream. 393 * @param count The number of data values. 394 * @param data The actual data content of the field. 395 * 396 * @throws NullPointerException if {@code tag == null}. 397 * @throws IllegalArgumentException if {@code type} is not 398 * one of the {@code TIFFTag.TIFF_*} data type constants. 399 * @throws IllegalArgumentException if {@code type} is an unacceptable 400 * data type for the supplied {@code TIFFTag}. 401 * @throws IllegalArgumentException if {@code count < 0}. 402 * @throws IllegalArgumentException if {@code count < 1} 403 * and {@code type} is {@code TIFF_RATIONAL} or 404 * {@code TIFF_SRATIONAL}. 405 * @throws IllegalArgumentException if {@code count != 1} 406 * and {@code type} is {@code TIFF_IFD_POINTER}. 407 * @throws NullPointerException if {@code data == null}. 408 * @throws IllegalArgumentException if {@code data} is an instance of 409 * a class incompatible with the specified type. 410 * @throws IllegalArgumentException if the size of the data array is wrong. 411 * @throws IllegalArgumentException if the type of the data array is 412 * {@code TIFF_LONG}, {@code TIFF_RATIONAL}, or {@code TIFF_IFD_POINTER} 413 * and any of the elements is negative or greater than {@code 0xffffffff}. 414 */ 415 public TIFFField(TIFFTag tag, int type, int count, Object data) { 416 if(tag == null) { 417 throw new NullPointerException("tag == null!"); 418 } else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) { 419 throw new IllegalArgumentException("Unknown data type "+type); 420 } else if(!tag.isDataTypeOK(type)) { 421 throw new IllegalArgumentException("Illegal data type " + type 422 + " for " + tag.getName() + " tag"); 423 } else if(count < 0) { 424 throw new IllegalArgumentException("count < 0!"); 425 } else if((type == TIFFTag.TIFF_RATIONAL 426 || type == TIFFTag.TIFF_SRATIONAL) 427 && count < 1) { 428 throw new IllegalArgumentException 429 ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1"); 430 } else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) { 431 throw new IllegalArgumentException 432 ("Type is TIFF_IFD_POINTER and count != 1"); 433 } else if(data == null) { 434 throw new NullPointerException("data == null!"); 435 } 436 437 boolean isDataArrayCorrect = false; 438 439 switch (type) { 440 case TIFFTag.TIFF_BYTE: 441 case TIFFTag.TIFF_SBYTE: 442 case TIFFTag.TIFF_UNDEFINED: 443 isDataArrayCorrect = data instanceof byte[] 444 && ((byte[])data).length == count; 445 break; 446 case TIFFTag.TIFF_ASCII: 447 isDataArrayCorrect = data instanceof String[] 448 && ((String[])data).length == count; 449 break; 450 case TIFFTag.TIFF_SHORT: 451 isDataArrayCorrect = data instanceof char[] 452 && ((char[])data).length == count; 453 break; 454 case TIFFTag.TIFF_LONG: 455 isDataArrayCorrect = data instanceof long[] 456 && ((long[])data).length == count; 457 if (isDataArrayCorrect) { 458 for (long datum : (long[])data) { 459 if (datum < 0) { 460 throw new IllegalArgumentException 461 ("Negative value supplied for TIFF_LONG"); 462 } 463 if (datum > MAX_UINT32) { 464 throw new IllegalArgumentException 465 ("Too large value supplied for TIFF_LONG"); 466 } 467 } 468 } 469 break; 470 case TIFFTag.TIFF_IFD_POINTER: 471 isDataArrayCorrect = data instanceof long[] 472 && ((long[])data).length == 1; 473 if (((long[])data)[0] < 0) { 474 throw new IllegalArgumentException 475 ("Negative value supplied for TIFF_IFD_POINTER"); 476 } 477 if (((long[])data)[0] > MAX_UINT32) { 478 throw new IllegalArgumentException 479 ("Too large value supplied for TIFF_IFD_POINTER"); 480 } 481 break; 482 case TIFFTag.TIFF_RATIONAL: 483 isDataArrayCorrect = data instanceof long[][] 484 && ((long[][])data).length == count; 485 if (isDataArrayCorrect) { 486 for (long[] datum : (long[][])data) { 487 if (datum.length != 2) { 488 isDataArrayCorrect = false; 489 break; 490 } 491 if (datum[0] < 0 || datum[1] < 0) { 492 throw new IllegalArgumentException 493 ("Negative value supplied for TIFF_RATIONAL"); 494 } 495 if (datum[0] > MAX_UINT32 || datum[1] > MAX_UINT32) { 496 throw new IllegalArgumentException 497 ("Too large value supplied for TIFF_RATIONAL"); 498 } 499 } 500 } 501 break; 502 case TIFFTag.TIFF_SSHORT: 503 isDataArrayCorrect = data instanceof short[] 504 && ((short[])data).length == count; 505 break; 506 case TIFFTag.TIFF_SLONG: 507 isDataArrayCorrect = data instanceof int[] 508 && ((int[])data).length == count; 509 break; 510 case TIFFTag.TIFF_SRATIONAL: 511 isDataArrayCorrect = data instanceof int[][] 512 && ((int[][])data).length == count; 513 if (isDataArrayCorrect) { 514 for (int[] datum : (int[][])data) { 515 if (datum.length != 2) { 516 isDataArrayCorrect = false; 517 break; 518 } 519 } 520 } 521 break; 522 case TIFFTag.TIFF_FLOAT: 523 isDataArrayCorrect = data instanceof float[] 524 && ((float[])data).length == count; 525 break; 526 case TIFFTag.TIFF_DOUBLE: 527 isDataArrayCorrect = data instanceof double[] 528 && ((double[])data).length == count; 529 break; 530 default: 531 throw new IllegalArgumentException("Unknown data type "+type); 532 } 533 534 if (!isDataArrayCorrect) { 535 throw new IllegalArgumentException 536 ("Illegal class or length for data array"); 537 } 538 539 this.tag = tag; 540 this.tagNumber = tag.getNumber(); 541 this.type = type; 542 this.count = count; 543 this.data = data; 544 } 545 546 /** 547 * Constructs a data array using {@link #createArrayForType 548 * createArrayForType()} and invokes 549 * {@link #TIFFField(TIFFTag,int,int,Object)} with the supplied 550 * parameters and the created array. 551 * 552 * @param tag The tag to associated with this field. 553 * @param type One of the {@code TIFFTag.TIFF_*} constants 554 * indicating the data type of the field as written to the TIFF stream. 555 * @param count The number of data values. 556 * @throws NullPointerException if {@code tag == null}. 557 * @throws IllegalArgumentException if {@code type} is not 558 * one of the {@code TIFFTag.TIFF_*} data type constants. 559 * @throws IllegalArgumentException if {@code type} is an unacceptable 560 * data type for the supplied {@code TIFFTag}. 561 * @throws IllegalArgumentException if {@code count < 0}. 562 * @see #TIFFField(TIFFTag,int,int,Object) 563 * @throws IllegalArgumentException if {@code count < 1} 564 * and {@code type} is {@code TIFF_RATIONAL} or 565 * {@code TIFF_SRATIONAL}. 566 * @throws IllegalArgumentException if {@code count != 1} 567 * and {@code type} is {@code TIFF_IFD_POINTER}. 568 */ 569 public TIFFField(TIFFTag tag, int type, int count) { 570 this(tag, type, count, createArrayForType(type, count)); 571 } 572 573 /** 574 * Constructs a {@code TIFFField} with a single non-negative integral 575 * value. The field will have type {@link TIFFTag#TIFF_SHORT TIFF_SHORT} 576 * if {@code value} is in {@code [0,0xffff]}, and type 577 * {@link TIFFTag#TIFF_LONG TIFF_LONG} if {@code value} is in 578 * {@code [0x10000,0xffffffff]}. The count of the field will be unity. 579 * 580 * @param tag The tag to associate with this field. 581 * @param value The value to associate with this field. 582 * @throws NullPointerException if {@code tag == null}. 583 * @throws IllegalArgumentException if {@code value} is not in 584 * {@code [0,0xffffffff]}. 585 * @throws IllegalArgumentException if {@code value} is in 586 * {@code [0,0xffff]} and {@code TIFF_SHORT} is an unacceptable type 587 * for the {@code TIFFTag}, or if {@code value} is in 588 * {@code [0x10000,0xffffffff]} and {@code TIFF_LONG} is an unacceptable 589 * type for the {@code TIFFTag}. 590 */ 591 public TIFFField(TIFFTag tag, long value) { 592 if(tag == null) { 593 throw new NullPointerException("tag == null!"); 594 } 595 if (value < 0) { 596 throw new IllegalArgumentException("value < 0!"); 597 } 598 if (value > MAX_UINT32) { 599 throw new IllegalArgumentException("value > 0xffffffff!"); 600 } 601 602 this.tag = tag; 603 this.tagNumber = tag.getNumber(); 604 this.count = 1; 605 606 if (value < 65536) { 607 if (!tag.isDataTypeOK(TIFFTag.TIFF_SHORT)) { 608 throw new IllegalArgumentException("Illegal data type " 609 + getTypeName(TIFFTag.TIFF_SHORT) + " for tag " 610 + "\"" + tag.getName() + "\""); 611 } 612 this.type = TIFFTag.TIFF_SHORT; 613 char[] cdata = new char[1]; 614 cdata[0] = (char)value; 615 this.data = cdata; 616 } else { 617 if (!tag.isDataTypeOK(TIFFTag.TIFF_LONG)) { 618 throw new IllegalArgumentException("Illegal data type " 619 + getTypeName(TIFFTag.TIFF_LONG) + " for tag " 620 + "\"" + tag.getName() + "\""); 621 } 622 this.type = TIFFTag.TIFF_LONG; 623 long[] ldata = new long[1]; 624 ldata[0] = value; 625 this.data = ldata; 626 } 627 } 628 629 /** 630 * Constructs a {@code TIFFField} with an IFD offset and contents. 631 * The offset will be stored as the data of this field as 632 * {@code long[] {offset}}. The directory will not be cloned. The count 633 * of the field will be unity. 634 * 635 * @param tag The tag to associated with this field. 636 * @param type One of the constants {@code TIFFTag.TIFF_LONG} or 637 * {@code TIFFTag.TIFF_IFD_POINTER}. 638 * @param offset The IFD offset. 639 * @param dir The directory. 640 * 641 * @throws NullPointerException if {@code tag == null}. 642 * @throws IllegalArgumentException if {@code type} is an unacceptable 643 * data type for the supplied {@code TIFFTag}. 644 * @throws IllegalArgumentException if {@code type} is neither 645 * {@code TIFFTag.TIFF_LONG} nor {@code TIFFTag.TIFF_IFD_POINTER}. 646 * @throws IllegalArgumentException if {@code offset <= 0}. 647 * @throws NullPointerException if {@code dir == null}. 648 * 649 * @see #TIFFField(TIFFTag,int,int,Object) 650 */ 651 public TIFFField(TIFFTag tag, int type, long offset, TIFFDirectory dir) { 652 if (tag == null) { 653 throw new NullPointerException("tag == null!"); 654 } else if (type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) { 655 throw new IllegalArgumentException("Unknown data type "+type); 656 } else if (!tag.isDataTypeOK(type)) { 657 throw new IllegalArgumentException("Illegal data type " + type 658 + " for " + tag.getName() + " tag"); 659 } else if (type != TIFFTag.TIFF_LONG 660 && type != TIFFTag.TIFF_IFD_POINTER) { 661 throw new IllegalArgumentException("type " + type 662 + " is neither TIFFTag.TIFF_LONG nor TIFFTag.TIFF_IFD_POINTER"); 663 } else if (offset <= 0) { 664 throw new IllegalArgumentException("offset " + offset 665 + " is non-positive"); 666 } else if (dir == null) { 667 throw new NullPointerException("dir == null"); 668 } 669 670 this.tag = tag; 671 this.tagNumber = tag.getNumber(); 672 this.type = type; 673 this.count = 1; 674 this.data = new long[] {offset}; 675 676 this.dir = dir; 677 } 678 679 /** 680 * Retrieves the tag associated with this field. 681 * 682 * @return The associated {@code TIFFTag}. 683 */ 684 public TIFFTag getTag() { 685 return tag; 686 } 687 688 /** 689 * Retrieves the tag number in the range {@code [0,65535]}. 690 * 691 * @return The tag number. 692 */ 693 public int getTagNumber() { 694 return tagNumber; 695 } 696 697 /** 698 * Returns the type of the data stored in the field. For a TIFF 6.0 699 * stream, the value will equal one of the {@code TIFFTag.TIFF_*} 700 * constants. For future revisions of TIFF, higher values are possible. 701 * 702 * @return The data type of the field value. 703 */ 704 public int getType() { 705 return type; 706 } 707 708 /** 709 * Returns the name of the supplied data type constant. 710 * 711 * @param dataType One of the {@code TIFFTag.TIFF_*} constants 712 * indicating the data type of the field as written to the TIFF stream. 713 * @return The type name corresponding to the supplied type constant. 714 * @throws IllegalArgumentException if {@code dataType} is not 715 * one of the {@code TIFFTag.TIFF_*} data type constants. 716 */ 717 public static String getTypeName(int dataType) { 718 if (dataType < TIFFTag.MIN_DATATYPE || 719 dataType > TIFFTag.MAX_DATATYPE) { 720 throw new IllegalArgumentException("Unknown data type "+dataType); 721 } 722 723 return TYPE_NAMES[dataType]; 724 } 725 726 /** 727 * Returns the data type constant corresponding to the supplied data 728 * type name. If the name is unknown {@code -1} will be returned. 729 * 730 * @param typeName The type name. 731 * @return One of the {@code TIFFTag.TIFF_*} constants or 732 * {@code -1} if the name is not recognized. 733 */ 734 public static int getTypeByName(String typeName) { 735 for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) { 736 if (typeName.equals(TYPE_NAMES[i])) { 737 return i; 738 } 739 } 740 741 return -1; 742 } 743 744 /** 745 * Creates an array appropriate for the indicated data type. 746 * 747 * @param dataType One of the {@code TIFFTag.TIFF_*} data type 748 * constants. 749 * @param count The number of values in the array. 750 * @return An array appropriate for the specified data type. 751 * 752 * @throws IllegalArgumentException if {@code dataType} is not 753 * one of the {@code TIFFTag.TIFF_*} data type constants. 754 * @throws IllegalArgumentException if {@code count < 0}. 755 * @throws IllegalArgumentException if {@code count < 1} 756 * and {@code type} is {@code TIFF_RATIONAL} or 757 * {@code TIFF_SRATIONAL}. 758 * @throws IllegalArgumentException if {@code count != 1} 759 * and {@code type} is {@code TIFF_IFD_POINTER}. 760 */ 761 public static Object createArrayForType(int dataType, int count) { 762 763 if(count < 0) { 764 throw new IllegalArgumentException("count < 0!"); 765 } else if ((dataType == TIFFTag.TIFF_RATIONAL 766 || dataType == TIFFTag.TIFF_SRATIONAL) 767 && count < 1) { 768 throw new IllegalArgumentException 769 ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1"); 770 } else if (dataType == TIFFTag.TIFF_IFD_POINTER && count != 1) { 771 throw new IllegalArgumentException 772 ("Type is TIFF_IFD_POINTER and count != 1"); 773 } 774 775 switch (dataType) { 776 case TIFFTag.TIFF_BYTE: 777 case TIFFTag.TIFF_SBYTE: 778 case TIFFTag.TIFF_UNDEFINED: 779 return new byte[count]; 780 case TIFFTag.TIFF_ASCII: 781 return new String[count]; 782 case TIFFTag.TIFF_SHORT: 783 return new char[count]; 784 case TIFFTag.TIFF_LONG: 785 case TIFFTag.TIFF_IFD_POINTER: 786 return new long[count]; 787 case TIFFTag.TIFF_RATIONAL: 788 return new long[count][2]; 789 case TIFFTag.TIFF_SSHORT: 790 return new short[count]; 791 case TIFFTag.TIFF_SLONG: 792 return new int[count]; 793 case TIFFTag.TIFF_SRATIONAL: 794 return new int[count][2]; 795 case TIFFTag.TIFF_FLOAT: 796 return new float[count]; 797 case TIFFTag.TIFF_DOUBLE: 798 return new double[count]; 799 default: 800 throw new IllegalArgumentException("Unknown data type "+dataType); 801 } 802 } 803 804 /** 805 * Returns the {@code TIFFField} as a node named either 806 * {@code "TIFFField"} or {@code "TIFFIFD"} as described in the 807 * TIFF native image metadata specification. The node will be named 808 * {@code "TIFFIFD"} if and only if {@link #hasDirectory()} returns 809 * {@code true} and the field's type is either {@link TIFFTag#TIFF_LONG} 810 * or {@link TIFFTag#TIFF_IFD_POINTER}. 811 * 812 * @return a {@code Node} named {@code "TIFFField"} or 813 * {@code "TIFFIFD"}. 814 */ 815 public Node getAsNativeNode() { 816 return new TIFFFieldNode(this); 817 } 818 819 /** 820 * Indicates whether the value associated with the field is of 821 * integral data type. 822 * 823 * @return Whether the field type is integral. 824 */ 825 public boolean isIntegral() { 826 return IS_INTEGRAL[type]; 827 } 828 829 /** 830 * Returns the number of data items present in the field. For 831 * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the 832 * number of {@code String}s, not the total length of the 833 * data as in the file representation. 834 * 835 * @return The number of data items present in the field. 836 */ 837 public int getCount() { 838 return count; 839 } 840 841 /** 842 * Returns a reference to the data object associated with the field. 843 * 844 * @return The data object of the field. 845 */ 846 public Object getData() { 847 return data; 848 } 849 850 /** 851 * Returns the data as an uninterpreted array of 852 * {@code byte}s. The type of the field must be one of 853 * {@code TIFFTag.TIFF_BYTE}, {@code TIFF_SBYTE}, or 854 * {@code TIFF_UNDEFINED}. 855 * 856 * <p> For data in {@code TIFFTag.TIFF_BYTE} format, the application 857 * must take care when promoting the data to longer integral types 858 * to avoid sign extension. 859 * 860 * @throws ClassCastException if the field is not of type 861 * {@code TIFF_BYTE}, {@code TIFF_SBYTE}, or 862 * {@code TIFF_UNDEFINED}. 863 * @return The data as an uninterpreted array of bytes. 864 */ 865 public byte[] getAsBytes() { 866 return (byte[])data; 867 } 868 869 /** 870 * Returns {@code TIFFTag.TIFF_SHORT} data as an array of 871 * {@code char}s (unsigned 16-bit integers). 872 * 873 * @throws ClassCastException if the field is not of type 874 * {@code TIFF_SHORT}. 875 * @return The data as an array of {@code char}s. 876 */ 877 public char[] getAsChars() { 878 return (char[])data; 879 } 880 881 /** 882 * Returns {@code TIFFTag.TIFF_SSHORT} data as an array of 883 * {@code short}s (signed 16-bit integers). 884 * 885 * @throws ClassCastException if the field is not of type 886 * {@code TIFF_SSHORT}. 887 * @return The data as an array of {@code short}s. 888 */ 889 public short[] getAsShorts() { 890 return (short[])data; 891 } 892 893 /** 894 * Returns {@code TIFFTag.TIFF_SLONG} data as an array of 895 * {@code int}s (signed 32-bit integers). 896 * 897 * @throws ClassCastException if the field is not of type 898 * {@code TIFF_SHORT}, {@code TIFF_SSHORT}, or 899 * {@code TIFF_SLONG}. 900 * @return The data as an array of {@code int}s. 901 */ 902 public int[] getAsInts() { 903 if (data instanceof int[]) { 904 return (int[])data; 905 } else if (data instanceof char[]){ 906 char[] cdata = (char[])data; 907 int[] idata = new int[cdata.length]; 908 for (int i = 0; i < cdata.length; i++) { 909 idata[i] = cdata[i] & 0xffff; 910 } 911 return idata; 912 } else if (data instanceof short[]){ 913 short[] sdata = (short[])data; 914 int[] idata = new int[sdata.length]; 915 for (int i = 0; i < sdata.length; i++) { 916 idata[i] = (int)sdata[i]; 917 } 918 return idata; 919 } else { 920 throw new ClassCastException("Data not char[], short[], or int[]!"); 921 } 922 } 923 924 /** 925 * Returns {@code TIFFTag.TIFF_LONG} or 926 * {@code TIFF_IFD_POINTER} data as an array of 927 * {@code long}s (signed 64-bit integers). 928 * 929 * @throws ClassCastException if the field is not of type 930 * {@code TIFF_LONG} or {@code TIFF_IFD_POINTER}. 931 * @return The data as an array of {@code long}s. 932 */ 933 public long[] getAsLongs() { 934 return (long[])data; 935 } 936 937 /** 938 * Returns {@code TIFFTag.TIFF_FLOAT} data as an array of 939 * {@code float}s (32-bit floating-point values). 940 * 941 * @throws ClassCastException if the field is not of type 942 * {@code TIFF_FLOAT}. 943 * @return The data as an array of {@code float}s. 944 */ 945 public float[] getAsFloats() { 946 return (float[])data; 947 } 948 949 /** 950 * Returns {@code TIFFTag.TIFF_DOUBLE} data as an array of 951 * {@code double}s (64-bit floating-point values). 952 * 953 * @throws ClassCastException if the field is not of type 954 * {@code TIFF_DOUBLE}. 955 * @return The data as an array of {@code double}s. 956 */ 957 public double[] getAsDoubles() { 958 return (double[])data; 959 } 960 961 /** 962 * Returns {@code TIFFTag.TIFF_SRATIONAL} data as an array of 963 * 2-element arrays of {@code int}s. 964 * 965 * @throws ClassCastException if the field is not of type 966 * {@code TIFF_SRATIONAL}. 967 * @return The data as an array of signed rationals. 968 */ 969 public int[][] getAsSRationals() { 970 return (int[][])data; 971 } 972 973 /** 974 * Returns {@code TIFFTag.TIFF_RATIONAL} data as an array of 975 * 2-element arrays of {@code long}s. 976 * 977 * @throws ClassCastException if the field is not of type 978 * {@code TIFF_RATIONAL}. 979 * @return The data as an array of unsigned rationals. 980 */ 981 public long[][] getAsRationals() { 982 return (long[][])data; 983 } 984 985 /** 986 * Returns data in any format as an {@code int}. 987 * 988 * <p> {@code TIFFTag.TIFF_BYTE} values are treated as unsigned; that 989 * is, no sign extension will take place and the returned value 990 * will be in the range [0, 255]. {@code TIFF_SBYTE} data 991 * will be returned in the range [-128, 127]. 992 * 993 * <p> A {@code TIFF_UNDEFINED} value is treated as though 994 * it were a {@code TIFF_BYTE}. 995 * 996 * <p> Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, 997 * {@code TIFF_FLOAT}, {@code TIFF_DOUBLE} or 998 * {@code TIFF_IFD_POINTER} format are simply cast to 999 * {@code int} and may suffer from truncation. 1000 * 1001 * <p> Data in {@code TIFF_SRATIONAL} or 1002 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1003 * numerator into the denominator using double-precision 1004 * arithmetic and then casting to {@code int}. Loss of 1005 * precision and truncation may occur. 1006 * 1007 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1008 * the {@code Double.parseDouble} method, with the result 1009 * case to {@code int}. 1010 * 1011 * @param index The index of the data. 1012 * @return The data at the given index as an {@code int}. 1013 */ 1014 public int getAsInt(int index) { 1015 switch (type) { 1016 case TIFFTag.TIFF_BYTE: 1017 case TIFFTag.TIFF_UNDEFINED: 1018 return ((byte[])data)[index] & 0xff; 1019 case TIFFTag.TIFF_SBYTE: 1020 return ((byte[])data)[index]; 1021 case TIFFTag.TIFF_SHORT: 1022 return ((char[])data)[index] & 0xffff; 1023 case TIFFTag.TIFF_SSHORT: 1024 return ((short[])data)[index]; 1025 case TIFFTag.TIFF_SLONG: 1026 return ((int[])data)[index]; 1027 case TIFFTag.TIFF_LONG: 1028 case TIFFTag.TIFF_IFD_POINTER: 1029 return (int)((long[])data)[index]; 1030 case TIFFTag.TIFF_FLOAT: 1031 return (int)((float[])data)[index]; 1032 case TIFFTag.TIFF_DOUBLE: 1033 return (int)((double[])data)[index]; 1034 case TIFFTag.TIFF_SRATIONAL: 1035 int[] ivalue = getAsSRational(index); 1036 return (int)((double)ivalue[0]/ivalue[1]); 1037 case TIFFTag.TIFF_RATIONAL: 1038 long[] lvalue = getAsRational(index); 1039 return (int)((double)lvalue[0]/lvalue[1]); 1040 case TIFFTag.TIFF_ASCII: 1041 String s = ((String[])data)[index]; 1042 return (int)Double.parseDouble(s); 1043 default: 1044 throw new ClassCastException(); // should never happen 1045 } 1046 } 1047 1048 /** 1049 * Returns data in any format as a {@code long}. 1050 * 1051 * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data 1052 * are treated as unsigned; that is, no sign extension will take 1053 * place and the returned value will be in the range [0, 255]. 1054 * {@code TIFF_SBYTE} data will be returned in the range 1055 * [-128, 127]. 1056 * 1057 * <p> Data in {@code TIFF_FLOAT} and {@code TIFF_DOUBLE} are 1058 * simply cast to {@code long} and may suffer from truncation. 1059 * 1060 * <p> Data in {@code TIFF_SRATIONAL} or 1061 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1062 * numerator into the denominator using double-precision 1063 * arithmetic and then casting to {@code long}. Loss of 1064 * precision and truncation may occur. 1065 * 1066 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1067 * the {@code Double.parseDouble} method, with the result 1068 * cast to {@code long}. 1069 * 1070 * @param index The index of the data. 1071 * @return The data at the given index as a {@code long}. 1072 */ 1073 public long getAsLong(int index) { 1074 switch (type) { 1075 case TIFFTag.TIFF_BYTE: 1076 case TIFFTag.TIFF_UNDEFINED: 1077 return ((byte[])data)[index] & 0xff; 1078 case TIFFTag.TIFF_SBYTE: 1079 return ((byte[])data)[index]; 1080 case TIFFTag.TIFF_SHORT: 1081 return ((char[])data)[index] & 0xffff; 1082 case TIFFTag.TIFF_SSHORT: 1083 return ((short[])data)[index]; 1084 case TIFFTag.TIFF_SLONG: 1085 return ((int[])data)[index]; 1086 case TIFFTag.TIFF_LONG: 1087 case TIFFTag.TIFF_IFD_POINTER: 1088 return ((long[])data)[index]; 1089 case TIFFTag.TIFF_FLOAT: 1090 return (long)((float[])data)[index]; 1091 case TIFFTag.TIFF_DOUBLE: 1092 return (long)((double[])data)[index]; 1093 case TIFFTag.TIFF_SRATIONAL: 1094 int[] ivalue = getAsSRational(index); 1095 return (long)((double)ivalue[0]/ivalue[1]); 1096 case TIFFTag.TIFF_RATIONAL: 1097 long[] lvalue = getAsRational(index); 1098 return (long)((double)lvalue[0]/lvalue[1]); 1099 case TIFFTag.TIFF_ASCII: 1100 String s = ((String[])data)[index]; 1101 return (long)Double.parseDouble(s); 1102 default: 1103 throw new ClassCastException(); // should never happen 1104 } 1105 } 1106 1107 /** 1108 * Returns data in any format as a {@code float}. 1109 * 1110 * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data 1111 * are treated as unsigned; that is, no sign extension will take 1112 * place and the returned value will be in the range [0, 255]. 1113 * {@code TIFF_SBYTE} data will be returned in the range 1114 * [-128, 127]. 1115 * 1116 * <p> Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, 1117 * {@code TIFF_DOUBLE}, or {@code TIFF_IFD_POINTER} format are 1118 * simply cast to {@code float} and may suffer from 1119 * truncation. 1120 * 1121 * <p> Data in {@code TIFF_SRATIONAL} or 1122 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1123 * numerator into the denominator using double-precision 1124 * arithmetic and then casting to {@code float}. 1125 * 1126 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1127 * the {@code Double.parseDouble} method, with the result 1128 * cast to {@code float}. 1129 * 1130 * @param index The index of the data. 1131 * @return The data at the given index as a {@code float}. 1132 */ 1133 public float getAsFloat(int index) { 1134 switch (type) { 1135 case TIFFTag.TIFF_BYTE: 1136 case TIFFTag.TIFF_UNDEFINED: 1137 return ((byte[])data)[index] & 0xff; 1138 case TIFFTag.TIFF_SBYTE: 1139 return ((byte[])data)[index]; 1140 case TIFFTag.TIFF_SHORT: 1141 return ((char[])data)[index] & 0xffff; 1142 case TIFFTag.TIFF_SSHORT: 1143 return ((short[])data)[index]; 1144 case TIFFTag.TIFF_SLONG: 1145 return ((int[])data)[index]; 1146 case TIFFTag.TIFF_LONG: 1147 case TIFFTag.TIFF_IFD_POINTER: 1148 return ((long[])data)[index]; 1149 case TIFFTag.TIFF_FLOAT: 1150 return ((float[])data)[index]; 1151 case TIFFTag.TIFF_DOUBLE: 1152 return (float)((double[])data)[index]; 1153 case TIFFTag.TIFF_SRATIONAL: 1154 int[] ivalue = getAsSRational(index); 1155 return (float)((double)ivalue[0]/ivalue[1]); 1156 case TIFFTag.TIFF_RATIONAL: 1157 long[] lvalue = getAsRational(index); 1158 return (float)((double)lvalue[0]/lvalue[1]); 1159 case TIFFTag.TIFF_ASCII: 1160 String s = ((String[])data)[index]; 1161 return (float)Double.parseDouble(s); 1162 default: 1163 throw new ClassCastException(); // should never happen 1164 } 1165 } 1166 1167 /** 1168 * Returns data in any format as a {@code double}. 1169 * 1170 * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data 1171 * are treated as unsigned; that is, no sign extension will take 1172 * place and the returned value will be in the range [0, 255]. 1173 * {@code TIFF_SBYTE} data will be returned in the range 1174 * [-128, 127]. 1175 * 1176 * <p> Data in {@code TIFF_SRATIONAL} or 1177 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1178 * numerator into the denominator using double-precision 1179 * arithmetic. 1180 * 1181 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1182 * the {@code Double.parseDouble} method. 1183 * 1184 * @param index The index of the data. 1185 * @return The data at the given index as a {@code double}. 1186 */ 1187 public double getAsDouble(int index) { 1188 switch (type) { 1189 case TIFFTag.TIFF_BYTE: 1190 case TIFFTag.TIFF_UNDEFINED: 1191 return ((byte[])data)[index] & 0xff; 1192 case TIFFTag.TIFF_SBYTE: 1193 return ((byte[])data)[index]; 1194 case TIFFTag.TIFF_SHORT: 1195 return ((char[])data)[index] & 0xffff; 1196 case TIFFTag.TIFF_SSHORT: 1197 return ((short[])data)[index]; 1198 case TIFFTag.TIFF_SLONG: 1199 return ((int[])data)[index]; 1200 case TIFFTag.TIFF_LONG: 1201 case TIFFTag.TIFF_IFD_POINTER: 1202 return ((long[])data)[index]; 1203 case TIFFTag.TIFF_FLOAT: 1204 return ((float[])data)[index]; 1205 case TIFFTag.TIFF_DOUBLE: 1206 return ((double[])data)[index]; 1207 case TIFFTag.TIFF_SRATIONAL: 1208 int[] ivalue = getAsSRational(index); 1209 return (double)ivalue[0]/ivalue[1]; 1210 case TIFFTag.TIFF_RATIONAL: 1211 long[] lvalue = getAsRational(index); 1212 return (double)lvalue[0]/lvalue[1]; 1213 case TIFFTag.TIFF_ASCII: 1214 String s = ((String[])data)[index]; 1215 return Double.parseDouble(s); 1216 default: 1217 throw new ClassCastException(); // should never happen 1218 } 1219 } 1220 1221 /** 1222 * Returns a {@code TIFFTag.TIFF_ASCII} value as a 1223 * {@code String}. 1224 * 1225 * @throws ClassCastException if the field is not of type 1226 * {@code TIFF_ASCII}. 1227 * 1228 * @param index The index of the data. 1229 * @return The data at the given index as a {@code String}. 1230 */ 1231 public String getAsString(int index) { 1232 return ((String[])data)[index]; 1233 } 1234 1235 /** 1236 * Returns a {@code TIFFTag.TIFF_SRATIONAL} data item as a 1237 * two-element array of {@code int}s. 1238 * 1239 * @param index The index of the data. 1240 * @return The data at the given index as a signed rational. 1241 * @throws ClassCastException if the field is not of type 1242 * {@code TIFF_SRATIONAL}. 1243 */ 1244 public int[] getAsSRational(int index) { 1245 return ((int[][])data)[index]; 1246 } 1247 1248 /** 1249 * Returns a TIFFTag.TIFF_RATIONAL data item as a two-element array 1250 * of ints. 1251 * 1252 * @param index The index of the data. 1253 * @return The data at the given index as an unsigned rational. 1254 * @throws ClassCastException if the field is not of type 1255 * {@code TIFF_RATIONAL}. 1256 */ 1257 public long[] getAsRational(int index) { 1258 return ((long[][])data)[index]; 1259 } 1260 1261 1262 /** 1263 * Returns a {@code String} containing a human-readable 1264 * version of the data item. Data of type 1265 * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} are 1266 * represented as a pair of integers separated by a 1267 * {@code '/'} character. If the numerator of a 1268 * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} is an integral 1269 * multiple of the denominator, then the value is represented as 1270 * {@code "q/1"} where {@code q} is the quotient of the numerator and 1271 * denominator. 1272 * 1273 * @param index The index of the data. 1274 * @return The data at the given index as a {@code String}. 1275 * @throws ClassCastException if the field is not of one of the 1276 * legal field types. 1277 */ 1278 public String getValueAsString(int index) { 1279 switch (type) { 1280 case TIFFTag.TIFF_ASCII: 1281 return ((String[])data)[index]; 1282 case TIFFTag.TIFF_BYTE: 1283 case TIFFTag.TIFF_UNDEFINED: 1284 return Integer.toString(((byte[])data)[index] & 0xff); 1285 case TIFFTag.TIFF_SBYTE: 1286 return Integer.toString(((byte[])data)[index]); 1287 case TIFFTag.TIFF_SHORT: 1288 return Integer.toString(((char[])data)[index] & 0xffff); 1289 case TIFFTag.TIFF_SSHORT: 1290 return Integer.toString(((short[])data)[index]); 1291 case TIFFTag.TIFF_SLONG: 1292 return Integer.toString(((int[])data)[index]); 1293 case TIFFTag.TIFF_LONG: 1294 case TIFFTag.TIFF_IFD_POINTER: 1295 return Long.toString(((long[])data)[index]); 1296 case TIFFTag.TIFF_FLOAT: 1297 return Float.toString(((float[])data)[index]); 1298 case TIFFTag.TIFF_DOUBLE: 1299 return Double.toString(((double[])data)[index]); 1300 case TIFFTag.TIFF_SRATIONAL: 1301 int[] ivalue = getAsSRational(index); 1302 String srationalString; 1303 if(ivalue[1] != 0 && ivalue[0] % ivalue[1] == 0) { 1304 // If the denominator is a non-zero integral divisor 1305 // of the numerator then convert the fraction to be 1306 // with respect to a unity denominator. 1307 srationalString = 1308 Integer.toString(ivalue[0] / ivalue[1]) + "/1"; 1309 } else { 1310 // Use the values directly. 1311 srationalString = 1312 Integer.toString(ivalue[0]) + 1313 "/" + 1314 Integer.toString(ivalue[1]); 1315 } 1316 return srationalString; 1317 case TIFFTag.TIFF_RATIONAL: 1318 long[] lvalue = getAsRational(index); 1319 String rationalString; 1320 if(lvalue[1] != 0L && lvalue[0] % lvalue[1] == 0) { 1321 // If the denominator is a non-zero integral divisor 1322 // of the numerator then convert the fraction to be 1323 // with respect to a unity denominator. 1324 rationalString = 1325 Long.toString(lvalue[0] / lvalue[1]) + "/1"; 1326 } else { 1327 // Use the values directly. 1328 rationalString = 1329 Long.toString(lvalue[0]) + 1330 "/" + 1331 Long.toString(lvalue[1]); 1332 } 1333 return rationalString; 1334 default: 1335 throw new ClassCastException(); // should never happen 1336 } 1337 } 1338 1339 /** 1340 * Returns whether the field has a {@code TIFFDirectory}. 1341 * 1342 * @return true if and only if getDirectory() returns non-null. 1343 */ 1344 public boolean hasDirectory() { 1345 return getDirectory() != null; 1346 } 1347 1348 /** 1349 * Returns the associated {@code TIFFDirectory}, if available. If no 1350 * directory is set, then {@code null} will be returned. 1351 * 1352 * @return the TIFFDirectory instance or null. 1353 */ 1354 public TIFFDirectory getDirectory() { 1355 return dir; 1356 } 1357 1358 /** 1359 * Clones the field and all the information contained therein. 1360 * 1361 * @return A clone of this {@code TIFFField}. 1362 * @throws CloneNotSupportedException if the instance cannot be cloned. 1363 */ 1364 @Override 1365 public TIFFField clone() throws CloneNotSupportedException { 1366 TIFFField field = (TIFFField)super.clone(); 1367 1368 Object fieldData; 1369 switch (type) { 1370 case TIFFTag.TIFF_BYTE: 1371 case TIFFTag.TIFF_UNDEFINED: 1372 case TIFFTag.TIFF_SBYTE: 1373 fieldData = ((byte[])data).clone(); 1374 break; 1375 case TIFFTag.TIFF_SHORT: 1376 fieldData = ((char[])data).clone(); 1377 break; 1378 case TIFFTag.TIFF_SSHORT: 1379 fieldData = ((short[])data).clone(); 1380 break; 1381 case TIFFTag.TIFF_SLONG: 1382 fieldData = ((int[])data).clone(); 1383 break; 1384 case TIFFTag.TIFF_LONG: 1385 case TIFFTag.TIFF_IFD_POINTER: 1386 fieldData = ((long[])data).clone(); 1387 break; 1388 case TIFFTag.TIFF_FLOAT: 1389 fieldData = ((float[])data).clone(); 1390 break; 1391 case TIFFTag.TIFF_DOUBLE: 1392 fieldData = ((double[])data).clone(); 1393 break; 1394 case TIFFTag.TIFF_SRATIONAL: 1395 fieldData = ((int[][])data).clone(); 1396 break; 1397 case TIFFTag.TIFF_RATIONAL: 1398 fieldData = ((long[][])data).clone(); 1399 break; 1400 case TIFFTag.TIFF_ASCII: 1401 fieldData = ((String[])data).clone(); 1402 break; 1403 default: 1404 throw new ClassCastException(); // should never happen 1405 } 1406 1407 field.tag = tag; 1408 field.tagNumber = tagNumber; 1409 field.type = type; 1410 field.count = count; 1411 field.data = fieldData; 1412 field.dir = dir != null ? dir.clone() : null; 1413 1414 return field; 1415 } 1416 }