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